傳送門
前兩個操作都比較基礎。對於第三個操作分類討論一下,首先如果當前根不是要操作點的子樹,那麼就無影響,直接查詢操作點的子樹即可。第二種是當前根是操作點的子樹,那就找到當前根到操作點這條鏈的頂端(也就是操作點的兒子,這個兒子為當前根的祖先),然後將這塊連續的\(dfs\)序挖掉,查詢兩邊就行了。找這個點的時候用倍增即可。(暴力往上跳也能過)
#include#include#include#includeusing namespace std;
const int maxn = 100005;
inline int rd()
while(isdigit(ch))
return f?x:-x;
}int n,m,head[maxn],cnt,to[maxn<<1],nxt[maxn<<1],w[maxn],wt[maxn],rt,num,g[maxn][20];
int siz[maxn],fa[maxn],son[maxn],id[maxn],min[maxn<<2],tag[maxn<<2],top[maxn],dep[maxn];
inline int min(int x,int y) }}
void dfs2(int x,int topf)
}void build(int x,int l,int r)
int mid=(l+r)>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
min[x]=min(min[x<<1],min[x<<1|1]);
}inline void pushdown(int x)
void update(int x,int l,int r,int l,int r,int k)
int mid=(l+r)>>1;if(tag[x]) pushdown(x);
if(l<=mid) update(x<<1,l,mid,l,r,k);
if(mid>1,ret=0x7fffffff;if(tag[x]) pushdown(x);
if(l<=mid) ret=min(ret,query(x<<1,l,mid,l,r));
if(middep[y]) swap(x,y);update(1,1,n,id[x],id[y],k);
}inline int qrange(int x,int y)
return x;
}inline int qson(int x)
int main()
for(int i=1;i<=n;i++) w[i]=rd();rt=rd();
dfs1(rt,0,1);dfs2(rt,rt);build(1,1,n);
while(m--)
if(op==3)
} return 0;
}
BZOJ 3083 遙遠的國度 樹剖
一開始看到有換根操作可是把我嚇了一跳,我還以為要上top tree呢,結果一開題解。心塞 如果除去換根操作的話就是一道裸的樹鏈剖分了,沒什麼難度,但是加上換根操作以後,別怕,其實聯絡查詢的點和現在的根節點只有4種可能 分3種操作 這裡的討論均基於以1為根節點的有根樹討論 1.x rt 直接查詢整個樹...
BZOJ3083 遙遠的國度 樹剖
zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神rapid阻攔了zcwwzdjn的去路,他需要zcwwzdjn完成任務後才能進入遙遠的國度繼續追殺。問題是這樣的 遙遠的國度有n個城市,這些城市之間由一些路連線且這些城市構成了...
BZOJ 3083 遙遠的國度 樹鏈剖分
題目大意 給出一顆無根樹,有鏈的修改操作,還有子樹的查詢。除此之外,還有選定這棵樹的乙個點為根。思路 子樹操作,鏈上修改,帶size域的樹鏈剖分就可以搞定。換根肯定不能真的換,出題人要是閒的沒事所有操作都在換根就慘。我們可以畫一張圖模擬下換根。先按照讀入的順序建一顆有根樹,然後觀察當前的根在要詢問的...