NOI2015软件包管理器
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;
}
 
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号