[NOI2015] 软件包管理器
题目链接:戳我
树链剖分维护。
1表示安装的状态,0表示没有安装的状态。
如果install就是把当前点到根的所有点都变成1,然后计算前后的\(\delta\)
如果uninstall呢,就是把自己的子树变成0,答案也是前后的\(\delta\)
具体可以参照代码(不过我的代码常数好大啊,跑得好慢。。。。)
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 400010
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
return x*f;
}
int n,m,t,tot;
int head[MAXN],sum[MAXN],tag[MAXN],siz[MAXN],top[MAXN],dep[MAXN],son[MAXN],id[MAXN],fa[MAXN];
char cur[20];
struct Edge{int nxt,to,dis;}edge[MAXN<<1];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
inline void add(int from,int to,int dis)
{
edge[++t].to=to,edge[t].nxt=head[from],edge[t].dis=dis;
head[from]=t;
}
inline void push_up(int x){sum[x]=sum[ls(x)]+sum[rs(x)];}
inline void push_down(int x,int l,int r)
{
if(tag[x]==0) return;
if(tag[x]==1)
{
tag[ls(x)]=tag[rs(x)]=1;
sum[ls(x)]=(r-l+1)-(r-l+1)/2;
sum[rs(x)]=(r-l+1)/2;
}
else
{
tag[ls(x)]=tag[rs(x)]=-1;
sum[ls(x)]=sum[rs(x)]=0;
}
tag[x]=0;
}
inline void update(int x,int l,int r,int ll,int rr,int k)
{
if(ll<=l&&r<=rr)
{
sum[x]=(r-l+1)*k;
tag[x]=(k==1?1:2);
return;
}
int mid=(l+r)>>1;
push_down(x,l,r);
if(ll<=mid) update(ls(x),l,mid,ll,rr,k);
if(mid<rr) update(rs(x),mid+1,r,ll,rr,k);
push_up(x);
}
inline int query(int x,int l,int r,int ll,int rr)
{
if(ll<=l&&r<=rr) return sum[x];
int mid=(l+r)>>1;
push_down(x,l,r);
int cur_ans=0;
if(ll<=mid) cur_ans+=query(ls(x),l,mid,ll,rr);
if(mid<rr) cur_ans+=query(rs(x),mid+1,r,ll,rr);
return cur_ans;
}
inline void dfs1(int x,int pre)
{
int maxx=-1;
dep[x]=dep[pre]+1;
fa[x]=pre;
siz[x]=1;
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v!=pre)
{
dfs1(v,x);
siz[x]+=siz[v];
if(siz[v]>maxx) maxx=siz[v],son[x]=v;
}
}
}
inline void dfs2(int x,int topf)
{
id[x]=++tot;
top[x]=topf;
if(son[x]) dfs2(son[x],topf);
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v!=fa[x]&&v!=son[x]) dfs2(v,v);
}
}
inline int modify(int x,int y,int k)
{
int cur_ans=0;
while(top[x]!=top[y])
{
if(dep[x]<dep[y]) swap(x,y);
cur_ans-=query(1,1,n,id[top[x]],id[x]);
update(1,1,n,id[top[x]],id[x],k);
cur_ans+=query(1,1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
cur_ans-=query(1,1,n,id[y],id[x]);
update(1,1,n,id[y],id[x],k);
cur_ans+=query(1,1,n,id[y],id[x]);
return cur_ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
n=read();
for(int i=1;i<n;i++)
{
int cur=read()+1;
add(cur,i+1,0),add(i+1,cur,0);
}
m=read();
dfs1(1,0);
dfs2(1,1);
for(int i=1;i<=m;i++)
{
scanf("%s",cur);
int x=read()+1;
if(cur[0]=='i')
printf("%d\n",modify(1,x,1));
else
{
printf("%d\n",query(1,1,n,id[x],id[x]+siz[x]-1));
update(1,1,n,id[x],id[x]+siz[x]-1,0);
}
}
return 0;
}