• [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
    ",download(readint()));else{
    			int p=readint();
    			printf("%d
    ",del_T(1,n,1,dfn[p],dfn[p]+sz[p]-1));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    MIT 6.828 JOS学习笔记10. Lab 1 Part 3: The kernel
    Java基础知识点4:继承
    CentOS Installation
    超微主板创建RAID磁盘阵列
    MySQL查询语句
    Psql操作命令
    Let's Encrypt 免费 SSL 证书续期
    Linux系统禁用swap分区
    公共 NTP 服务器地址
    Postgresql配置
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7778801.html
Copyright © 2020-2023  润新知