码迷,mamicode.com
首页 > 其他好文 > 详细

NOI2015软件包管理器

时间:2017-04-08 10:10:34      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:query   void   UI   efi   ++   之间   inpu   输出   const   

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;
}

 

  

 

NOI2015软件包管理器

标签:query   void   UI   efi   ++   之间   inpu   输出   const   

原文地址:http://www.cnblogs.com/ypz999/p/6680663.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!