题意是有n个没有安装的软件包形成一个树形结构,安装一个软件包必须把它的所有祖先一起安装,卸载一个软件包必须把它的所有子孙一起卸载。
q次操作,每次可能安装一个节点也可能卸载一个节点,问每次操作会改变多少个节点的状态。
安装是对链操作,卸载是对子树操作。线段树维护区间内的安装数量与未安装数量,更新的时候如果安装就把没安装的lazy变为0,并把所有节点状态变为安装,卸载同理。查询的时候每次安装查询没安装的节点,卸载查询安装的节点即可。
#include <bits/stdc++.h> #define Lson l,mid,rt<<1 #define Rson mid+1,r,rt<<1|1 using namespace std; const int M = 1e5+7; char op[20]; int n,q,tot,cnt,head[M]; int sz[M],f[M],son[M],dep[M],rnk[M],top[M],id[M]; struct edge{ int v,next; }e[M<<1]; struct Tree { int zeronum,onenum; int lazy,lazy1; }tree[M<<2]; void init(){ tot=cnt=0;memset(head,-1,sizeof(head)); } void add(int u,int v){ e[++cnt].v=v;e[cnt].next=head[u]; head[u]=cnt; } /**********************找重儿子**********************/ void dfs(int u,int fa,int d){ sz[u]=1,f[u]=fa,son[u]=-1,dep[u]=d; for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa) continue; dfs(v,u,d+1); sz[u]+=sz[v]; if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v; } return ; } void dfs1(int u,int t){ //cout<<u<<endl; id[u]=++tot; rnk[tot]=u; top[u]=t; if(son[u]==-1) return ; dfs1(son[u],t); for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==f[u]||v==son[u]) continue; dfs1(v,v); } return ; } /**********************线段树**********************/ void Pushup(int rt,int l,int r){ tree[rt].zeronum=tree[l].zeronum+tree[r].zeronum; tree[rt].onenum=tree[l].onenum+tree[r].onenum; } void Pushdown(int rt,int l,int r){ if(tree[rt].lazy){//如果是安装状态 tree[rt].lazy=0; tree[l].lazy=tree[r].lazy=1; tree[l].lazy1=tree[r].lazy1=0; tree[l].onenum+=tree[l].zeronum;tree[l].zeronum=0; tree[r].onenum+=tree[r].zeronum;tree[r].zeronum=0; //cout<<tree[rt].zeronum<<" "<<tree[rt].onenum<<endl; } else if(tree[rt].lazy1){//卸载状态 没写if又多调半个小时 心累 tree[rt].lazy1=0; tree[l].lazy=tree[r].lazy=0; tree[l].lazy1=tree[r].lazy1=1; tree[l].zeronum+=tree[l].onenum;tree[l].onenum=0; tree[r].zeronum+=tree[r].onenum;tree[r].onenum=0; //cout<<tree[rt].zeronum<<" "<<tree[rt].onenum<<endl; } } void build(int l,int r,int rt){ tree[rt].lazy=0; if(l==r){ tree[rt].zeronum=1;tree[rt].onenum=0; return ; } int mid=(l+r)>>1; build(Lson); build(Rson); Pushup(rt,rt<<1,rt<<1|1); } void update(int L,int R,int l,int r,int rt,int ff){ if(L<=l&&r<=R){ if(ff==0){ tree[rt].lazy=1;tree[rt].lazy1=0; tree[rt].onenum+=tree[rt].zeronum;tree[rt].zeronum=0; } else{ tree[rt].lazy1=1;tree[rt].lazy=0; tree[rt].zeronum+=tree[rt].onenum;tree[rt].onenum=0; } return ; } Pushdown(rt,rt<<1,rt<<1|1); int mid=(l+r)>>1; if(L<=mid) update(L,R,Lson,ff); if(R>mid) update(L,R,Rson,ff); Pushup(rt,rt<<1,rt<<1|1); } int query(int L,int R,int l,int r,int rt,int ff){ if(L<=l&&r<=R){ //cout<<tree[rt].zeronum<<" "<<tree[rt].onenum<<endl; if(ff==1) return tree[rt].onenum; else return tree[rt].zeronum; } Pushdown(rt,rt<<1,rt<<1|1); int mid=(l+r)>>1,res=0; if(L<=mid) res+=query(L,R,Lson,ff); if(R>mid) res+=query(L,R,Rson,ff); //cout<<rt<<" "<<res<<endl; return res; } /**********************剖分**********************/ void updates(int x,int y,int ff){ int fx=top[x],fy=top[y]; while(fx!=fy){ if(dep[fx]>dep[fy]){ update(id[fx],id[x],1,n,1,ff); x=f[fx],fx=top[x]; } else{ update(id[fy],id[y],1,n,1,ff); y=f[fy],fy=top[y]; } } if(dep[x]<dep[y]) update(id[x],id[y],1,n,1,ff); else update(id[y],id[x],1,n,1,ff); } int sum(int x,int y,int ff){ int fx=top[x],fy=top[y],res=0; while(fx!=fy){ if(dep[fx]>dep[fy]){ res+=query(id[fx],id[x],1,n,1,ff); x=f[fx],fx=top[x]; } else{ res+=query(id[fy],id[y],1,n,1,ff); y=f[fy],fy=top[y]; } } if(dep[x]<dep[y]) res+=query(id[x],id[y],1,n,1,ff); else res+=query(id[y],id[x],1,n,1,ff); return res; } int main(){ init(); scanf("%d",&n); for(int i=2;i<=n;i++){ int u; scanf("%d",&u); add(u+1,i);add(i,u+1); } dfs(1,-1,1);dfs1(1,1); build(1,n,1); scanf("%d",&q); while(q--){ int x; scanf("%s%d",op,&x);x++; if(op[0]=='i'){ //cout<<tree[8].zeronum<<" "<<tree[8].onenum<<endl; printf("%d\n",sum(1,x,0)); updates(1,x,0); } else{ printf("%d\n",query(id[x],id[x]+sz[x]-1,1,n,1,1)); update(id[x],id[x]+sz[x]-1,1,n,1,1); } } return 0; }