BZOJ4196: [Noi2015]软件包管理器 (好题
好题啊,做到这题想起以前靠线段树维护子树的时候
那时候没见过链操作,搞不清树剖有什么用
这题就结合了子树操作和树链操作,也是把dfs序的in out完整用上了
树剖exp++
#include<bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const int maxn=1e5+9; //int arr[maxn]; int n; struct EDGE{ int v;int next; }G[maxn<<2]; int head[maxn],tot; void init(){ memset(head,-1,sizeof head);tot=0; } void addedge(int u,int v){ ++tot;G[tot].v=v;G[tot].next=head[u];head[u]=tot; } int top[maxn]; int pre[maxn]; int dep[maxn]; int num[maxn]; int p[maxn]; //v的对应位置 int out[maxn]; //退出时间戳 int fp[maxn]; //访问序列 int son[maxn]; //重儿子 int pos; void dfs1(int u,int fa,int d){ dep[u]=d; pre[u]=fa; num[u]=1; for(int i=head[u];~i;i=G[i].next){ int v=G[i].v; if(v==fa)continue; dfs1(v,u,d+1); num[u]+=num[v]; if(son[u]==-1||num[v]>num[son[u]])son[u]=v; } } void getpos(int u,int sp){ top[u]=sp; p[u]=out[u]=++pos; fp[p[u]]=u; if(son[u]==-1)return; getpos(son[u],sp); for(int i=head[u];~i;i=G[i].next){ int v=G[i].v; if(v!=son[u]&&v!=pre[u])getpos(v,v); } out[u]=pos; } struct NODE{ int lazy; int add; int sum; }ST[maxn<<2]; void pushup(int rt){ ST[rt].sum=ST[rt<<1].sum+ST[rt<<1|1].sum; } void pushdown(int l,int r,int rt){ if(ST[rt].lazy){ int m=l+r>>1; ST[rt<<1].add=ST[rt<<1|1].add=ST[rt].add; ST[rt<<1].sum=(m-l+1)*ST[rt].add;ST[rt<<1].lazy=1; ST[rt<<1|1].sum=(r-m)*ST[rt].add;ST[rt<<1|1].lazy=1; ST[rt].lazy=0; } } void update(int a,int b,int c,int l,int r,int rt){ if(a<=l&&b>=r){ ST[rt].sum=(r-l+1)*c; ST[rt].lazy=1; ST[rt].add=c;return; } int m=l+r>>1;pushdown(l,r,rt); if(a<=m)update(a,b,c,l,m,rt<<1);if(b>m)update(a,b,c,m+1,r,rt<<1|1); pushup(rt); } int query(int a,int b,int l,int r,int rt){ if(a<=l&&b>=r){return ST[rt].sum;} int m=l+r>>1;pushdown(l,r,rt); int ans=0; if(a<=m)ans+=query(a,b,l,m,rt<<1);if(b>m)ans+=query(a,b,m+1,r,rt<<1|1); return ans; } void solve(int u,int v){ int ans=0; while(top[u]!=top[v]){ ans+=(-p[top[u]]+p[u])+1-query(p[top[u]],p[u],1,n,1); update(p[top[u]],p[u],1,1,n,1); u=pre[top[u]]; } ans+=p[u]-p[v]+1-query(p[v],p[u],1,n,1); update(p[v],p[u],1,1,n,1); //cout<<query(p[0],p[0],1,n,1)<<endl; printf("%d\n",ans); } char op[15]; int main(){ memset(son,-1,sizeof son); scanf("%d",&n); init(); for(int i=1,x;i<n;i++){ scanf("%d",&x); addedge(x,i); } dfs1(0,-1,0); getpos(0,0); int q;scanf("%d",&q); int x; while(q--){ scanf("%s%d",op,&x); if(op[0]=='i')solve(x,0); else{ printf("%d\n",query(p[x],out[x],1,n,1)); update(p[x],out[x],0,1,n,1); } } }