题目:BZOJ4196、洛谷P2146、codevs4621、UOJ#128。
题目大意:有一些软件,编号0~n,它们之间有依赖关系,装编号为ai软件先要装编号为i的软件(编号为0的除外),卸载编号为i的软件必须先卸载编号为ai的软件(编号为0的除外)。它们的关系形成树形图。现在有m个任务,每次让你下载或卸载一个软件,问你本次操作一共新下载/卸载了多少软件。
解题思路:树链剖分。用线段树维护每个节点。
对于下载任务,就是将节点0到p修改成1,并统计修改了多少,对每条经过的链区间修改查询即可。
对于卸载任务,就是将以p为根的子树中所有节点修改为0,并统计修改了多少,对整个子树的区间修改查询即可。
C++ Code:
#include<cstdio> #include<cctype> #include<cstring> #define N 100005 #define mem(a) memset(&a,0,sizeof a) int n,fa[N],sz[N],head[N],cnt,son[N],dep[N],idx,dfn[N],d[N<<2],tag[N<<2],top[N]; struct edge{ int to,nxt; }e[N<<1]; inline int readint(){ char c=getchar(); for(;!isdigit(c);c=getchar()); int d=0; for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^'0'); return d; } void dfs(int now){ sz[now]=1; for(int i=head[now];i;i=e[i].nxt) if(!dep[e[i].to]){ dep[e[i].to]=dep[now]+1; dfs(e[i].to); sz[now]+=sz[e[i].to]; if(!son[now]||sz[e[i].to]>sz[son[now]])son[now]=e[i].to; } } void dfs2(int now){ dfn[now]=++idx; if(son[now])top[son[now]]=top[now],dfs2(son[now]); for(int i=head[now];i;i=e[i].nxt) if(dep[now]<dep[e[i].to]&&e[i].to!=son[now]) dfs2(top[e[i].to]=e[i].to); } int add_T(int l,int r,int o,int L,int R){ int ans=0; if(L<=l&&r<=R){ tag[o]=1; ans=r-l+1-d[o]; d[o]+=ans; return ans; } int mid=(l+r)>>1,le=o<<1,rr=o<<1|1; if(tag[o]==1){ d[le]=mid-l+1; d[rr]=r-mid; tag[le]=tag[rr]=1; tag[o]=0; }else if(tag[o]==-1){ d[le]=d[rr]=0; tag[le]=tag[rr]=-1; tag[o]=0; } if(L<=mid)ans=add_T(l,mid,le,L,R); if(mid<R)ans+=add_T(mid+1,r,rr,L,R); d[o]=d[le]+d[rr]; return ans; } int del_T(int l,int r,int o,int L,int R){ int ans=0; if(L<=l&&r<=R){ tag[o]=-1; ans=d[o]; d[o]=0; return ans; } int mid=(l+r)>>1,le=o<<1,rr=o<<1|1; if(tag[o]==1){ d[le]=mid-l+1; d[rr]=r-mid; tag[le]=tag[rr]=1; tag[o]=0; }else if(tag[o]==-1){ d[le]=d[rr]=0; tag[le]=tag[rr]=-1; tag[o]=0; } if(L<=mid)ans=del_T(l,mid,le,L,R); if(mid<R)ans+=del_T(mid+1,r,rr,L,R); d[o]=d[le]+d[rr]; return ans; } int download(int p){ int ans=0; while(top[p]){ ans+=add_T(1,n,1,dfn[top[p]],dfn[p]); p=fa[top[p]]; } return ans+add_T(1,n,1,1,dfn[p]); } int main(){ n=readint(); fa[0]=cnt=idx=0; mem(head); mem(son); mem(dep); mem(top); mem(d); mem(tag); dep[top[0]=0]=1; for(int i=1;i<n;++i){ fa[i]=readint(); e[++cnt]=(edge){i,head[fa[i]]}; head[fa[i]]=cnt; e[++cnt]=(edge){fa[i],head[i]}; head[i]=cnt; } dfs(0); dfs2(0); for(int opt=readint();opt--;){ char c=getchar(); for(;!isalpha(c);c=getchar()); if(c=='i') printf("%d ",download(readint()));else{ int p=readint(); printf("%d ",del_T(1,n,1,dfn[p],dfn[p]+sz[p]-1)); } } return 0; }