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 ",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 ",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 ",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 ",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 ",query(1,1,n,tid[u],oh[u])),Update(1,1,n,tid[u],oh[u],-1); } return 0; }