正题
这道题是一道很水的树上问题。
很容易我们就可以知道一个软件包只依赖另一个软件包,所以如果x依赖y,那么y就是x的父亲。
因此,就可以构造出一棵树。每个点有权值0/1表示不安装或者已安装
我们操作就转换成为了,询问根到该节点的路径上的点有多少个点为0,并把它们变为1.
或者询问该子树的节点有多少个为1,并把它们都变为0.
子树想到dfs序,动态路径想到树链剖分。所以结合起来就维护一下一棵子树的新编号最小节点(一定是自己因为是dfs序)和最大节点。然后按操作来即可。
image[x]表示x的新编号(该子树最小新编号),fact[x]表示x子树的最大新编号。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int n,m;
struct edge{
int y,next;
}u[100010];
int first[100010];
int len=0;
int dep[100010],tot[100010],image[100010],fact[100010],fa[100010],son[100010],top[100010];
struct tree{
int ls,rs,x,y,tot;
int lazy;
}s[200010];
void ins(int x,int y){
len++;u[len].next=first[x];first[x]=len;
u[len].y=y;
}
void build(int x,int y){
len++;
int i=len;
s[i].ls=s[i].rs=-1;
s[i].x=x;s[i].y=y;
s[i].tot=0;
s[i].lazy=-1;
if(x==y) return ;
int mid=(x+y)/2;
s[i].ls=len+1;build(x,mid);
s[i].rs=len+1;build(mid+1,y);
}
void dfs_1(int x){
tot[x]=1;
for(int i=first[x];i!=0;i=u[i].next){
int y=u[i].y;
fa[y]=x;
dep[y]=dep[x]+1;
dfs_1(y);
if(tot[y]>tot[son[x]]) son[x]=y;
tot[x]+=tot[y];
}
}
void dfs_2(int x,int tp){
top[x]=tp;image[x]=++len;
if(son[x]!=0) dfs_2(son[x],tp);
for(int i=first[x];i!=0;i=u[i].next){
int y=u[i].y;
if(y!=son[x]) dfs_2(y,y);
}
fact[x]=len;//记录最右端点方便操作
}
void pushdown(int x){
if(s[x].lazy==-1) return ;
int ls=s[x].ls,rs=s[x].rs;
s[ls].lazy=s[rs].lazy=s[x].lazy;
s[ls].tot=s[ls].lazy*(s[ls].y-s[ls].x+1);
s[rs].tot=s[rs].lazy*(s[rs].y-s[rs].x+1);
s[x].lazy=-1;
}
int get_sum(int now,int x,int y){
if(s[now].x==x && s[now].y==y)
return s[now].tot;
pushdown(now);
int mid=s[s[now].ls].y;
if(y<=mid) return get_sum(s[now].ls,x,y);
else if(mid<x) return get_sum(s[now].rs,x,y);
else return get_sum(s[now].ls,x,mid)+get_sum(s[now].rs,mid+1,y);
}
void change(int now,int x,int y,int c){
if(s[now].x==x && s[now].y==y){
s[now].lazy=c;
s[now].tot=(y-x+1)*c;
return ;
}
pushdown(now);
int mid=s[s[now].ls].y;
if(y<=mid) change(s[now].ls,x,y,c);
else if(mid<x) change(s[now].rs,x,y,c);
else {change(s[now].ls,x,mid,c);change(s[now].rs,mid+1,y,c);}
s[now].tot=s[s[now].ls].tot+s[s[now].rs].tot;
}
int install(){
int x;
scanf("%d",&x);
x++;
int tx=top[x];
int ans=0;
while(x!=0){
ans+=image[x]-image[tx]+1-get_sum(1,image[tx],image[x]);
change(1,image[tx],image[x],1);
x=fa[tx];tx=top[x];
}
return ans;
}
int uninstall(){
int x;
scanf("%d",&x);
x++;
int ans=get_sum(1,image[x],fact[x]);
change(1,image[x],fact[x],0);
return ans;
}
int main(){
scanf("%d",&n);
for(int i=2;i<=n;i++){
int x;
scanf("%d",&x);
x++;
ins(x,i);
}
dep[1]=1;dfs_1(1);
len=0;dfs_2(1,1);
len=0;
build(1,n);
scanf("%d",&m);
char ch[20];
while(m--){
scanf("%s",ch);
if(ch[0]=='i') printf("%d\n",install());
else printf("%d\n",uninstall());
}
}