[NOI2015]软件包管理器

Posted qjs12

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOI2015]软件包管理器相关的知识,希望对你有一定的参考价值。

  原来NOI也有这样的题啊,而且还和当年HAOI2015上午T2可以说是撞车了,当年HA的省队这道题应该都A了。

// q.c

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define lc o<<1
#define rc o<<1^1
using namespace std;
const int M=100000+10;
/**************************************************************************************/
struct Edge {
	int u,v,nex; Edge() {}
	Edge(int a,int b,int c):u(a),v(b),nex(c) {}
}ed[M<<1];
int head[M],cnt;
void add_edge(int a,int b) {
	ed[cnt]=Edge(a,b,head[a]); head[a]=cnt++;
	ed[cnt]=Edge(b,a,head[b]); head[b]=cnt++;
}
/**************************************************************************************/
int f[M],dep[M],size[M],son[M];
void dfs1(int u,int fa,int d) {
	f[u]=fa,size[u]=1,dep[u]=d;
	int i; Edge e;
	for(i=head[u];~i;i=ed[i].nex) {
		e=ed[i];
		if(!f[e.v]) {
			dfs1(e.v,u,d+1); size[u]+=size[e.v];
			if(size[e.v]>size[son[u]]||!son[u]) son[u]=e.v;
		}
	}
}
int top[M],id[M],nd[M],dck,LEFT[M];
void dfs2(int u,int TP) {
	top[u]=TP; LEFT[u]=id[u]=++dck; nd[dck]=u;
	if(!son[u]) return ; dfs2(son[u],TP);
	int i; Edge e; LEFT[u]=max(LEFT[u],LEFT[son[u]]);
	for(i=head[u];~i;i=ed[i].nex) {
		e=ed[i];
		if(e.v!=f[u]&&e.v!=son[u]) {
			dfs2(e.v,e.v);
			LEFT[u]=max(LEFT[u],LEFT[e.v]);
		}
	}
}
/**************************************************************************************/
int L[M<<2],R[M<<2],ins[M<<2],uns[M<<2],tag[M<<2];
void build(int o,int l,int r) {
	L[o]=l,R[o]=r,uns[o]=r-l+1; 
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(lc,l,mid); build(rc,mid+1,r);
}
void DOWN(int o) {
	if(tag[o]==1) {
		ins[lc]=R[lc]-L[lc]+1,uns[lc]=0,tag[lc]=1;
		ins[rc]=R[rc]-L[rc]+1,uns[rc]=0,tag[rc]=1;
	} else {
		ins[lc]=0,uns[lc]=R[lc]-L[lc]+1,tag[lc]=2;
		ins[rc]=0,uns[rc]=R[rc]-L[rc]+1,tag[rc]=2;
	}
	tag[o]=0;
}
void UP(int o) {
	ins[o]=ins[lc]+ins[rc]; uns[o]=uns[lc]+uns[rc];
}
int add(int o,int l,int r) {
	if(l<=L[o]&&R[o]<=r) {
		int tmp=uns[o];
		ins[o]=R[o]-L[o]+1,uns[o]=0,tag[o]=1;
		return tmp;
	} else {
		if(tag[o]) DOWN(o);
		int mid=(L[o]+R[o])>>1,ans=0;
		if(l<=mid) ans+=add(lc,l,r);
		if(r>mid) ans+=add(rc,l,r); UP(o);
		return ans;
	}
}
int sub(int o,int l,int r) {
	if(l<=L[o]&&R[o]<=r) {
		int tmp=ins[o];
		ins[o]=0,uns[o]=R[o]-L[o]+1,tag[o]=2;
		return tmp;
	} else {
		if(tag[o]) DOWN(o);
		int mid=(L[o]+R[o])>>1,ans=0;
		if(l<=mid) ans+=sub(lc,l,r);
		if(r>mid) ans+=sub(rc,l,r); UP(o);
		return ans;
	}
}
/**************************************************************************************/
int install(int a,int b) {
	int ans=0;
	while(top[a]!=top[b]) {
		if(dep[top[a]]<dep[top[b]]) swap(a,b);
		ans+=add(1,id[top[a]],id[a]);
		a=f[top[a]];
	}
	if(dep[a]>dep[b]) swap(a,b);
	return ans+add(1,id[a],id[b]);
}
int unstall(int a) {
	int ans=0;
	ans=sub(1,id[a],LEFT[a]);
	return ans;
}
/**************************************************************************************/
int main() {
	freopen("manager.in","r",stdin);
	freopen("manager.out","w",stdout);
	int n,q,a; char str[17];
	scanf("%d",&n);
	memset(head,-1,sizeof(head));
	for(int i=1;i<n;i++) { 
		scanf("%d",&a);
		add_edge(i+1,a+1);
	}
	dfs1(1,-1,0); dfs2(1,1); build(1,1,dck);
	scanf("%d",&q);
	for(int i=1;i<=q;i++) {
		scanf("%s%d",str,&a); ++a;
		if(str[0]==‘i‘) printf("%d\n",install(1,a));
		else printf("%d\n",unstall(a));
	}
	return 0;
}

 

以上是关于[NOI2015]软件包管理器的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4196 [Noi2015]软件包管理器——树链剖分

[BZOJ4196][Noi2015]软件包管理器

Bzoj 4196: [Noi2015]软件包管理器 树链剖分

bzoj 4196:[NOI2015] 软件包管理器 (树链剖分)

NOI2015软件包管理器

BZOJ 4196: [Noi2015]软件包管理器