題目大意:給定一棵有根樹,有以下操作:換根,鏈上修改,子樹查詢最小值。
樹鏈剖分配合線段樹可以輕鬆解決子樹查詢與鏈上修改,換根怎麼辦?
當然不能真的換根。設初始根為 root (也就是說樹剖處理時是以 root 為根的),當前根為 cur ,對於每一次查詢子樹x進行討論:
1.如果 x 就是 cur ,取所有點最小即可。
2.如果 x 的子樹包括 cur ,則對包括 cur 的子樹取補集查詢最小值。
3.不滿足以上兩種情況(即 x 在 cur 的子樹中 或 cur的子樹中沒有 x 且 x 的子樹中沒有 cur ),那麼 x 的子樹沒有變化,正常查詢即可。
還有一些細節,若查詢一段空區間(l>r) 應該返回乙個不影響答案的值否則re
#include
#include
#define n 100005
#define inf 2147483647
using namespace std;
inline int min(int
x,int
y) inline void swap(int& x,int& y)
struct edge e[n<<1];
int n,m,root,fir[n];
int t,val[n],dpt[n],siz[n],son[n],top[n],pa[n],seq[n],pos[n];
void dfs1(int
x) return ;
}void dfs2(int
x) return ;
}struct segment_tree s[n*4];
void pushdown(int
x) if(s[x].l!=s[x].r && s[x].flag>s[x
*2+1].flag)
s[x].flag=-1;
return ;
}void maintain(int
x) void init(int
x,int l,int r)
int mid=l+r>>1;
init(x
*2,l,mid); init(x
*2+1,mid+1,r);
maintain(x);
return ;
}void change(int
x,int l,int r,int v)
int mid=s[x].l+s[x].r>>1;
if(r<=mid) change(x
*2,l,r,v);
else
if(l>mid) change(x
*2+1,l,r,v);
else change(x
*2,l,mid,v) , change(x
*2+1,mid+1,r,v);
maintain(x);
return ;
}int get_min(int
x,int l,int r)
void to_change(int
x,int
y,int v)
if(dpt[x]y]) swap(x,y);
change(1,pos[y],pos[x],v);
return ;
}bool in_tree(int
x,int
y) int query_min(int
x) return min(get_min(1,1,rootl-1),get_min(1,rootr+1,n));
}int main()
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
scanf("%d",&root);
dfs1(1); dfs2(1);
init(1,1,n);
t=0;
while(m--)
if(mode==3)
}return
0;}
bzoj3083 遙遠的國度
題意 給定一棵樹,支援換根,路徑權值覆蓋,求子樹最小。思路 求子樹?上樹鏈剖分,但是換根怎麼辦?我們只能通過原有資訊推出換根後的答案。換根不影響路徑修改,所以只要考慮子樹最小值的維護。這裡要分3種情況討論 1 如果詢問點是當前根,直接返回整棵樹的最小值。2 如果在原樹中,當前根不在 x的子樹中,直接...
bzoj3083 遙遠的國度
time limit 10 sec memory limit 1280 mb submit 1733 solved 429 submit status discuss description 描述 zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的...
bzoj3083 遙遠的國度
time limit 10 sec memory limit 1280 mb submit 1960 solved 484 submit status discuss 描述zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神ra...