Test instructions
Give a tree, root=1, a tree a little power, there's a man called M
There are 3 types of operations:
1 U v the point of all points on the U-v path to M
2 U If you point right at M hand, take away
3 U to the root of the subtree of a bit of power to the M
After each operation, the output m has a point right
Idea:
To maintain the path, use the tree chain to split
To maintain subtrees, use the DFS sequence
But it seems like a lot to write.
But then I knew
The tree chain is a DFS sequence, that is, after the tree chain is split, for a point, the new number of all points of its subtree is just within a continuous interval after the new number of the point, the range of this interval [chg[u],chg[u]+siz[u]-1],
This is convenient, we just need a tree chain to split it.
The tree chain is then maintained with a segment tree,
The segment tree maintains 3 values:
All: If the interval is owned by M, all is 1, otherwise 0
Val: Within that interval, M has a bit of power and
Sum: Within that interval, the sum of the points of all points
(sum is fixed after build and does not need to be changed)
All we need is a update2: All and Val.
So after every update, the answer is Seg[1].val.
Actually, at first, I only maintained 2 values: All and Sum
And then every time I update, I'm going to ask for Val at a time, but it's definitely timed out.
When you add a val, the query function simply omits the
#pragmaComment (linker, "/stack:102400000,102400000")#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#defineLson l,m,rt<<1#defineRson m+1,r,rt<<1|1using namespacestd;Const intmaxn=1e5+Ten;Const intinf=0x3f3f3f3f;structseg{intall,val,sum;}; Seg SEG[MAXN<<2];intA[MAXN];intDEP[MAXN];intSIZ[MAXN];intSON[MAXN];intFA[MAXN];intTOP[MAXN];intCHG[MAXN];intREV[MAXN];structedge{intTo,next;}; Edge EDGE[MAXN<<1];intHEAD[MAXN];inttot;voidinit () {memset (head,-1,sizeofhead); Tot=0;}voidAddedge (intUintv) {edge[tot].to=v; Edge[tot].next=Head[u]; Head[u]=tot++;}voidSolveint );intMain () {inttest; scanf ("%d",&test); while(test--){ intN; scanf ("%d",&N); Init (); for(intI=1; i<=n;i++) {scanf ("%d",&A[i]); } for(intI=1; i<n;i++){ intu,v; scanf ("%d%d",&u,&v); Addedge (U,V); Addedge (V,u); } solve (n); } return 0;}voidDfs0 (intUintpre) {Fa[u]=Pre; Siz[u]=1; Dep[u]=dep[pre]+1; for(intI=head[u];~i;i=Edge[i].next) { intv=edge[i].to; if(v==pre)Continue; Dfs0 (V,u); Siz[u]+=Siz[v]; if(son[u]==-1|| Siz[v]>Siz[son[u]]) Son[u]=v; }}voidDFS1 (intUintTP) {Top[u]=TP; Chg[u]=++tot; Rev[tot]=u; if(son[u]==-1) return ; DFS1 (SON[U],TP); for(intI=head[u];~i;i=Edge[i].next) { intv=edge[i].to; if(V==fa[u] | | v==Son[u])Continue; DFS1 (V,V); }}voidPushup (intRT) {Seg[rt].val=seg[rt<<1].val+seg[rt<<1|1].val;}voidBuildintLintRintRT) {Seg[rt].sum=seg[rt].all=seg[rt].val=0; if(l==S) {Seg[rt].sum=A[rev[l]]; return ; } intM= (l+r) >>1; Build (Lson); Build (Rson); Seg[rt].sum=seg[rt<<1].sum+seg[rt<<1|1].sum;}voidPushdown (intRT) { if(seg[rt].all) {Seg[rt<<1].all=seg[rt<<1|1].all=1; Seg[rt<<1].val=seg[rt<<1].sum; Seg[rt<<1|1].val=seg[rt<<1|1].sum; Seg[rt].all=0; }}voidUPDATE_SEG (intLintRintAddintLintRintRT) { if(l<=l&&r>=R) {Seg[rt].all=add; if(add) seg[rt].val=seg[rt].sum; ElseSeg[rt].val=0; return ; } intM= (l+r) >>1; Pushdown (RT); if(l<=m) update_seg (L,r,add,lson); if(r>m) update_seg (L,r,add,rson); Pushup (RT);}voidUpdate_path (intUintv) { while(top[u]!=Top[v]) { if(dep[top[u]]<Dep[top[v]) swap (U,V); Update_seg (Chg[top[u]],chg[u],1,1Tot1); U=Fa[top[u]]; } if(dep[u]<Dep[v]) swap (U,V); Update_seg (Chg[v],chg[u],1,1Tot1);}voidSolveintN) {memset (son,-1,sizeofson); memset (DEP,0,sizeofDEP); Dfs0 (1,1); Tot=0; DFS1 (1,1); Build (1Tot1); intQ; scanf ("%d",&q); for(intI=1; i<=q;i++){ intop; scanf ("%d",&op); if(op==1){ intu,v; scanf ("%d%d",&u,&v); Update_path (U,V); } Else{ intu; scanf ("%d",&T); if(op==2) {update_seg (Chg[u],chg[u],0,1Tot1); } Else{update_seg (Chg[u],chg[u]+siz[u]-1,1,1Tot1); }} printf ("%d\n", seg[1].val); } return ;}
HDU5221 Occupation Tree Chain split