• 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说明:

    Pic

    一开始所有的软件包都处于未安装状态。
    安装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;
    }
    
     
    

      

     
  • 相关阅读:
    谈一谈循环的性能提升
    Web前端性能优化的9大问题
    随机获取一种颜色值的三种方法
    ES6还是ES2015?
    history.back(-1)和history.go(-1)的区别
    关于overflow-y:scroll ios设备不流畅的问题
    前端如何压缩图片
    【转】理解JavaScript之闭包
    关于如何给数字排序
    本地缓存localstorage使用
  • 原文地址:https://www.cnblogs.com/ypz999/p/6680663.html
Copyright © 2020-2023  润新知