[NOI2015]软件包管理器

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

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

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

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

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

C++ Code:

#include
#include
#include
#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]>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>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

 

转载于:https://www.cnblogs.com/Mrsrz/p/7778801.html

你可能感兴趣的:([NOI2015]软件包管理器)