P2146 [NOI2015]软件包管理器
https://www.luogu.com.cn/problem/P2146
题意:给出一棵树,然后有两种操作,安装与卸载;
安装就是,想要安装这个软件,就得安装这个软件之前的一个软件,即:他的父亲,他的父亲的父亲....
卸载就是,想要卸载这个软件,就得把这个软件的儿子都卸载了才能卸载;
那么他具体问的就是,每次安装(卸载)的操作,需要安装(卸载)多少个软件;
所以我们只需要处理处每一个安装包的状态,然后通过状态来计数即可;
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 const int mod=1e9+7; 5 struct node 6 { 7 int v,nxt; 8 }G[maxn*2]; int head[maxn]; int num; 9 int w[maxn],wt[maxn]; 10 //链式前向星数组,w[]、wt[]初始点权数组 11 int son[maxn],id[maxn],fa[maxn],cnt,dep[maxn],siz[maxn],top[maxn]; 12 void init() 13 { 14 memset(head,-1,sizeof(head)); 15 num=-1; 16 } 17 struct tre 18 { 19 int l,r,lazy,sum; 20 }tree[maxn<<2]; 21 void add(int u,int v) 22 { 23 G[++num].v=v;G[num].nxt=head[u];head[u]=num; 24 G[++num].v=u;G[num].nxt=head[v];head[v]=num; 25 } 26 27 void build(int l,int r,int root){ 28 tree[root].l=l;tree[root].r=r; 29 tree[root].sum=tree[root].lazy=0; 30 if(l==r){ 31 tree[root].sum=0; 32 return; 33 } 34 int mid=l+r>>1; 35 build(l,mid,root<<1); 36 build(mid+1,r,root<<1|1); 37 tree[root].sum=(tree[root<<1].sum+tree[root<<1|1].sum)%mod; 38 } 39 void pushdown(int rt,int lenn){ 40 tree[rt<<1].lazy=tree[rt].lazy; 41 tree[rt<<1|1].lazy=tree[rt].lazy; 42 if(tree[rt].lazy==1){ 43 tree[rt<<1].sum=tree[rt].lazy*(lenn-(lenn>>1)); 44 tree[rt<<1|1].sum=tree[rt].lazy*(lenn>>1); 45 } 46 else{ 47 tree[rt<<1].sum=tree[rt<<1|1].sum=0; 48 } 49 tree[rt].lazy=0; 50 } 51 void update(int l,int r,int val,int root){ 52 int L=tree[root].l;int R=tree[root].r; 53 if(l<=L&&R<=r){ 54 if(val) tree[root].lazy=val; 55 else tree[root].lazy=-1; 56 tree[root].sum=val*(R-L+1); 57 } 58 else{ 59 if(tree[root].lazy!=0)pushdown(root,R-L+1); 60 int mid=L+R>>1; 61 if(l<=mid)update(l,r,val,root<<1); 62 if(r>mid) update(l,r,val,root<<1|1); 63 tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum; 64 } 65 } 66 int query(int l,int r,int root,int flag){ 67 int L=tree[root].l;int R=tree[root].r; 68 if(l<=L&&R<=r){ 69 int tmp=tree[root].sum; 70 if(flag==0) return R-L+1-tmp; 71 else return tmp; 72 } 73 if(tree[root].lazy)pushdown(root,R-L+1); 74 int mid=L+R>>1; 75 int ans=0; 76 if(l<=mid) ans+=query(l,r,root<<1,flag); 77 if(r>mid) ans+=query(l,r,root<<1|1,flag); 78 return ans; 79 } 80 void dfs1(int u,int f,int deep){//x当前节点,f父亲,deep深度 81 dep[u]=deep;//标记每个点的深度 82 fa[u]=f;//标记每个点的父亲 83 siz[u]=1;//标记每个非叶子节点的子树大小 84 int maxson=-1;//记录重儿子的儿子数 85 for(int i=head[u];i!=-1;i=G[i].nxt){ 86 int v=G[i].v; 87 if(v==f)continue;//若为父亲则continue 88 dfs1(v,u,deep+1);//dfs其儿子 89 siz[u]+=siz[v];//把它的儿子数加到它身上 90 if(siz[v]>maxson)son[u]=v,maxson=siz[v];//标记每个非叶子节点的重儿子编号 91 } 92 } 93 94 void dfs2(int u,int topf){//x当前节点,topf当前链的最顶端的节点 95 id[u]=++cnt;//标记每个点的新编号 96 top[u]=topf;//这个点所在链的顶端 97 if(!son[u])return;//如果没有儿子则返回 98 dfs2(son[u],topf);//按先处理重儿子,再处理轻儿子的顺序递归处理 99 for(int i=head[u];i!=-1;i=G[i].nxt){ 100 int v=G[i].v; 101 if(v==fa[u]||v==son[u])continue; 102 dfs2(v,v);//对于每一个轻儿子都有一条从它自己开始的链 103 } 104 } 105 int qRange(int x,int y,int flag){ 106 int ans=0; 107 while(top[x]!=top[y]){//当两个点不在同一条链上 108 if(dep[top[x]]<dep[top[y]])swap(x,y);//把x点改为所在链顶端的深度更深的那个点 109 ans+=query(id[top[x]],id[x],1,flag);//ans加上x点到x所在链顶端 这一段区间的点权和 110 x=fa[top[x]];//把x跳到x所在链顶端的那个点的上面一个点 111 } 112 //直到两个点处于一条链上 113 if(dep[x]>dep[y])swap(x,y);//把x点深度更深的那个点 114 ans+=query(id[x],id[y],1,flag);//这时再加上此时两个点的区间和即可 115 return ans; 116 } 117 void updRange(int x,int y,int k){//同上 118 while(top[x]!=top[y]){ 119 if(dep[top[x]]<dep[top[y]])swap(x,y); 120 update(id[top[x]],id[x],k,1); 121 x=fa[top[x]]; 122 } 123 if(dep[x]>dep[y])swap(x,y); 124 update(id[x],id[y],k,1); 125 } 126 127 int main() 128 { 129 init(); 130 int n; 131 scanf("%d",&n); 132 for(int i=1;i<n;i++){ 133 int u,v; 134 v=i+1; scanf("%d",&u); 135 u++; 136 add(u,v); 137 } 138 dfs1(1,0,1); 139 dfs2(1,1); 140 build(1,n,1); 141 int q; 142 scanf("%d",&q); 143 while(q--){ 144 string tmp1; 145 int tmp2; 146 cin>>tmp1>>tmp2; 147 tmp2++; 148 if(tmp1[0]=='i'){ 149 printf("%d\n",qRange(1,tmp2,0)); 150 updRange(1,tmp2,1); 151 } 152 else{ 153 printf("%d\n",query(id[tmp2],id[tmp2]+siz[tmp2]-1,1,1)); 154 update(id[tmp2],id[tmp2]+siz[tmp2]-1,0,1); 155 } 156 } 157 return 0; 158 }