BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)
设白色结点为未安装的软件,黑色结点为已安装的软件,则:
安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色。复杂度$O(nlog^2n)$
卸载软件i:输出结点i子树下的黑色结点数量,并把结点i的子树染成白色。复杂度$O(nlogn)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,inf=0x3f3f3f3f; 5 int n,m,hd[N],ne,fa[N],son[N],siz[N],dep[N],top[N],dfn[N],rnk[N],ed[N],tot,sum[N<<2],mk[N<<2]; 6 struct E {int v,nxt;} e[N]; 7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;} 8 void dfs1(int u,int f,int d) { 9 fa[u]=f,son[u]=0,siz[u]=1,dep[u]=d; 10 for(int i=hd[u]; ~i; i=e[i].nxt) { 11 int v=e[i].v; 12 if(v==fa[u])continue; 13 dfs1(v,u,d+1),siz[u]+=siz[v]; 14 if(siz[v]>siz[son[u]])son[u]=v; 15 } 16 } 17 void dfs2(int u,int tp) { 18 top[u]=tp,dfn[u]=++tot,rnk[tot]=u; 19 if(son[u])dfs2(son[u],tp); 20 for(int i=hd[u]; ~i; i=e[i].nxt) { 21 int v=e[i].v; 22 if(v==fa[u]||v==son[u])continue; 23 dfs2(v,v); 24 } 25 ed[u]=tot; 26 } 27 #define ls (u<<1) 28 #define rs (u<<1|1) 29 #define mid ((l+r)>>1) 30 void pu(int u) {sum[u]=sum[ls]+sum[rs];} 31 void pd(int u,int l,int r) { 32 if(~mk[u]) { 33 sum[u]=mk[u]*(r-l+1); 34 if(l<r)mk[ls]=mk[rs]=mk[u]; 35 mk[u]=-1; 36 } 37 } 38 void upd(int L,int R,int x,int u=1,int l=1,int r=tot) { 39 pd(u,l,r); 40 if(l>=L&&r<=R) {mk[u]=x,pd(u,l,r); return;} 41 if(l>R||r<L)return; 42 upd(L,R,x,ls,l,mid),upd(L,R,x,rs,mid+1,r),pu(u); 43 } 44 int qry(int L,int R,int u=1,int l=1,int r=tot) { 45 pd(u,l,r); 46 if(l>=L&&r<=R)return sum[u]; 47 if(l>R||r<L)return 0; 48 return qry(L,R,ls,l,mid)+qry(L,R,rs,mid+1,r); 49 } 50 void changeroot(int u,int x) {for(; u; u=fa[top[u]])upd(dfn[top[u]],dfn[u],x);} 51 int askroot(int u) { 52 int ret=0; 53 for(; u; u=fa[top[u]])ret+=qry(dfn[top[u]],dfn[u]); 54 return ret; 55 } 56 void changesub(int u,int x) {upd(dfn[u],ed[u],x);} 57 int asksub(int u) {return qry(dfn[u],ed[u]);} 58 int main() { 59 memset(hd,-1,sizeof hd),ne=0; 60 scanf("%d",&n); 61 for(int i=2; i<=n; ++i) { 62 int u; 63 scanf("%d",&u),u++; 64 addedge(u,i); 65 } 66 tot=0,dfs1(1,0,1),dfs2(1,1); 67 memset(mk,-1,sizeof mk); 68 char s[10]; 69 scanf("%d",&m); 70 while(m--) { 71 int u; 72 scanf("%s%d",s,&u),u++; 73 if(s[0]=='i') { 74 printf("%d\n",dep[u]-askroot(u)); 75 changeroot(u,1); 76 } else { 77 printf("%d\n",asksub(u)); 78 changesub(u,0); 79 } 80 } 81 return 0; 82 }