P2106 - 【NOI2015】软件包管理器
Description
你决定设计你自己的软件包管理器。不可避免的,你要解决软件包之间的依赖关系。如果A依赖B,那么安装A之前需安装B,卸载B之前须卸载A。0号软件包不依赖任何软件包。依赖关系不存在环(包括自环)。
你的任务是,求出每次安装、删除操作会改变多少个包的状态。
安装一个已安装的软件包,或者卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0
每次操作不仅需要计算安装软件包数,还作为操作影响后来的安装/删除
Input
第一行一个整数n,表示软件包的总数。
随后n-1个整数a1,a2,...an-1,表示第i个软件包依赖第ai个软件包
接下来一行一个整数q,表示询问数
之后q行,每行一个询问,询问分为两种
install x:表示安装x
uninstall x:表示卸载x
Output
q行,每行一个整数,为第i步操作改变安装状态的软件包数
Sample Input
样例输入1:
7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0
样例输入2:
10
0 1 2 1 3 0 0 3 2
10
install 0
install 3
uninstall 2
install 7
install 5
install 9
uninstall 9
install 4
install 1
install 9
Sample Output
样例输出1:
3
1
3
2
3
样例输出2:
1
3
2
1
3
1
1
1
0
1
Hint
样例输入1说明:
一开始所有的软件包都处于未安装状态。
安装5号软件包,需安装0,1,5三个软件包
之后安装6号软件包,只需安装6号软件包。此时安装了0,1,5,6四个软件包。
卸载1号软件包需要卸载1,5,6三个软件包,此时只有0号软件包还处于安装状态
之后安装4号软件包,需安装1,4两个软件包。此时0,1,4处于安装状态
最后,卸载0号软件包会卸载所有的软件包
数据提示:
1,2:n=5000 q=5000
3,4:n=100000 q=100000 没有卸载操作
5,6,7,8 n=100000,q=100000 依赖关系和操作随机
9-20 n=100000,q=100000 不随机
#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define ll long long
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define inf 1<<30
#define il inline
#define ls o<<1
#define rs o<<1|1
#define re register
using namespace std;
const int N=100010;
struct Edge{
int to,net;
}e[N*2];
int head[N],dep[N],siz[N],top[N],tid[N],pos[N],son[N],fa[N],oh[N],idx,num_e,n;
int sum[N*4],lazy[N*4],len[N*4];
void add(int x,int y) {
e[++num_e].to=y;e[num_e].net=head[x];head[x]=num_e;
}
il int gi() {
int ret=0,f=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') f=-11,ch=getchar();
while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
void dfs1(int x,int f) {
dep[x]=dep[f]+1;
siz[x]=1;
fa[x]=f;
son[x]=n+1;// bug
for(int i=head[x];i;i=e[i].net) {
if(e[i].to==f) continue;
dfs1(e[i].to,x);
siz[x] += siz[e[i].to];
if(siz[e[i].to] > siz[son[x]]) son[x]=e[i].to;
}
}
void dfs2(int x,int tp) {
tid[x]=++idx;
pos[idx]=x;
top[x]=tp;
oh[x]=idx;
if(son[x]==n+1) return;// bug
dfs2(son[x],tp);
oh[x]=oh[son[x]];
for(int i=head[x];i;i=e[i].net) {
int to=e[i].to;
if(to!=son[x]&&to!=fa[x]) dfs2(to,to),oh[x]=max(oh[x],oh[to]);
}
}
void down(int o) {
if(lazy[o]==0) return;
if(lazy[o]==-1) {
lazy[ls]=lazy[rs]=-1;
sum[ls]=sum[rs]=0;
}
else {
lazy[ls]=lazy[rs]=1;
sum[ls]=len[ls];sum[rs]=len[rs];
}
lazy[o]=0;
}
int query(int o,int L,int R,int l,int r) {
if(L!=R) down(o);
if(l<=L&&R<=r) return sum[o];
int mid=(L+R)>>1,tot=0;
if(l<=mid) tot+=query(ls,L,mid,l,r);
if(r>mid) tot += query(rs,mid+1,R,l,r);
return tot;
}
void Update(int o,int L,int R,int l,int r,int x) {
if(L!=R) down(o);
if(l<=L&&R<=r) {
lazy[o]=x;
x==1 ? sum[o]=len[o] : sum[o]=0;
// printf("hear%d\n",len[o]);
return;
}
int mid=(L+R)>>1;
if(l<=mid) Update(ls,L,mid,l,r,x);
if(r>mid) Update(rs,mid+1,R,l,r,x);
sum[o]=sum[ls]+sum[rs];
}
void solve(int x,int y) {
int tot=0,g=0;
while(top[x]!=top[y]) {
if(dep[top[x]]>dep[top[y]]) swap(x,y);
// printf("%d %d\n",tid[top[y]],tid[y]);
tot += query(1,1,n,tid[top[y]],tid[y]);
g+=tid[y]-tid[top[y]]+1;
Update(1,1,n,tid[top[y]],tid[y],1);
y=fa[top[y]];
}
if(dep[x]>dep[y]) swap(x,y);
// printf("%d %d\n",tid[x],tid[y]);
tot +=query(1,1,n,tid[x],tid[y]);
g+=tid[y]-tid[x]+1;
Update(1,1,n,tid[x],tid[y],1);
printf("%d\n",g-tot);
}
void BB(int o,int L,int R) {
len[o]=R-L+1;
if(L==R) return;
int mid=(L+R)>>1;
BB(ls,L,mid);
BB(rs,mid+1,R);
}
int main() {
freopen("manager.in","r",stdin);
freopen("manager.out","w",stdout);
n=gi();re int u,v;
rep(i,1,n-1) u=gi(),add(u,i),add(i,u);
int q=gi();char s[2];
dfs1(0,-1);
dfs2(0,0);
BB(1,1,n);
// rep(i,0,n-1) printf("%d ",tid[i]);puts("");
while(q--) {
scanf("%s",s);
u=gi();
if(s[0]=='i') solve(0,u);
else printf("%d\n",query(1,1,n,tid[u],oh[u])),Update(1,1,n,tid[u],oh[u],-1);
}
return 0;
}