BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)

时间:2019-03-26
本文章向大家介绍BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树),主要包括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 }