[NOI2015]软件包管理器

题目:BZOJ4196、洛谷P2146、codevs4621、UOJ#128。

题目大意:有一些软件,编号0~n,它们之间有依赖关系,装编号为ai软件先要装编号为i的软件(编号为0的除外),卸载编号为i的软件必须先卸载编号为ai的软件(编号为0的除外)。它们的关系形成树形图。现在有m个任务,每次让你下载或卸载一个软件,问你本次操作一共新下载/卸载了多少软件。

解题思路:树链剖分。用线段树维护每个节点。

对于下载任务,就是将节点0到p修改成1,并统计修改了多少,对每条经过的链区间修改查询即可。

对于卸载任务,就是将以p为根的子树中所有节点修改为0,并统计修改了多少,对整个子树的区间修改查询即可。

C++ Code:

#include<cstdio>
#include<cctype>
#include<cstring>
#define N 100005
#define mem(a) memset(&a,0,sizeof a)
int n,fa[N],sz[N],head[N],cnt,son[N],dep[N],idx,dfn[N],d[N<<2],tag[N<<2],top[N];
struct edge{
	int to,nxt;
}e[N<<1];
inline int readint(){
	char c=getchar();
	for(;!isdigit(c);c=getchar());
	int d=0;
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^'0');
	return d;
}
void dfs(int now){
	sz[now]=1;
	for(int i=head[now];i;i=e[i].nxt)
	if(!dep[e[i].to]){
		dep[e[i].to]=dep[now]+1;
		dfs(e[i].to);
		sz[now]+=sz[e[i].to];
		if(!son[now]||sz[e[i].to]>sz[son[now]])son[now]=e[i].to;
	}
}
void dfs2(int now){
	dfn[now]=++idx;
	if(son[now])top[son[now]]=top[now],dfs2(son[now]);
	for(int i=head[now];i;i=e[i].nxt)
	if(dep[now]<dep[e[i].to]&&e[i].to!=son[now])
	dfs2(top[e[i].to]=e[i].to);
}
int add_T(int l,int r,int o,int L,int R){
	int ans=0;
	if(L<=l&&r<=R){
		tag[o]=1;
		ans=r-l+1-d[o];
		d[o]+=ans;
		return ans;
	}
	int mid=(l+r)>>1,le=o<<1,rr=o<<1|1;
	if(tag[o]==1){
		d[le]=mid-l+1;
		d[rr]=r-mid;
		tag[le]=tag[rr]=1;
		tag[o]=0;
	}else
	if(tag[o]==-1){
		d[le]=d[rr]=0;
		tag[le]=tag[rr]=-1;
		tag[o]=0;
	}
	if(L<=mid)ans=add_T(l,mid,le,L,R);
	if(mid<R)ans+=add_T(mid+1,r,rr,L,R);
	d[o]=d[le]+d[rr];
	return ans;
}
int del_T(int l,int r,int o,int L,int R){
	int ans=0;
	if(L<=l&&r<=R){
		tag[o]=-1;
		ans=d[o];
		d[o]=0;
		return ans;
	}
	int mid=(l+r)>>1,le=o<<1,rr=o<<1|1;
	if(tag[o]==1){
		d[le]=mid-l+1;
		d[rr]=r-mid;
		tag[le]=tag[rr]=1;
		tag[o]=0;
	}else
	if(tag[o]==-1){
		d[le]=d[rr]=0;
		tag[le]=tag[rr]=-1;
		tag[o]=0;
	}
	if(L<=mid)ans=del_T(l,mid,le,L,R);
	if(mid<R)ans+=del_T(mid+1,r,rr,L,R);
	d[o]=d[le]+d[rr];
	return ans;
}
int download(int p){
	int ans=0;
	while(top[p]){
		ans+=add_T(1,n,1,dfn[top[p]],dfn[p]);
		p=fa[top[p]];
	}
	return ans+add_T(1,n,1,1,dfn[p]);
}
int main(){
	n=readint();
	fa[0]=cnt=idx=0;
	mem(head);
	mem(son);
	mem(dep);
	mem(top);
	mem(d);
	mem(tag);
	dep[top[0]=0]=1;
	for(int i=1;i<n;++i){
		fa[i]=readint();
		e[++cnt]=(edge){i,head[fa[i]]};
		head[fa[i]]=cnt;
		e[++cnt]=(edge){fa[i],head[i]};
		head[i]=cnt;
	}
	dfs(0);
	dfs2(0);
	for(int opt=readint();opt--;){
		char c=getchar();
		for(;!isalpha(c);c=getchar());
		if(c=='i')
		printf("%d\n",download(readint()));else{
			int p=readint();
			printf("%d\n",del_T(1,n,1,dfn[p],dfn[p]+sz[p]-1));
		}
	}
	return 0;
}

 

posted @ 2017-11-03 16:22  Mrsrz  阅读(201)  评论(0)    收藏  举报