zoukankan      html  css  js  c++  java
  • [NOI2015]软件包管理器(巧用线段树)

    题目

    原题链接

    解说

    线段树基本板子的可塑性其实非常强悍,针对不同的题目要求只要稍作修改就可以发挥不同的作用。这道题让我更深刻地理解了这一点。

    本题和普通的树链剖分+线段树最大的区别在于它的每个结点并不储存一个数值,而是只有两种状态:安装与未安装。针对这一特点,我们对线段树的板子做以下修改即可:

    1. lazy标记:由于现在每个节点只有两种状态,(lazy)标记也只有两种数值就够了,比如(1)代表该区间所有软件全部被安装,(-1)代表该区间所有软件全部没有被安装。

    2. pushdown操作:之前(pushdown)仅仅把父节点的(lazy)标记下放即可,但现在(lazy)标记有两种,所以下放之前应当先判断:(lazy)标记为(1)则代表全部安装,那么就应当把子节点的安装数量变为区间内总节点数;(lazy)标记为(1)则代表全部卸载,那么就应当把子节点的安装数量变为(0)

    3. update操作:之前传参时传递的是向该区间内加的数,现在则应更改为操作模式,即卸载还是安装?安装则把(lazy)标记记为(1),把子节点的安装数量变为区间内总节点数;卸载则把(lazy)标记记为(-1),把子节点的安装数量变为(0)

    4. 其余操作均保持不变

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100000+3;
    int head[maxn],tot,dep[maxn],size[maxn],son[maxn],top[maxn],n,q,fa[maxn],dfn[maxn],dfn_clock;
    struct edge{
    	int to,next;
    }e[maxn<<1];
    struct node{
    	int l,r,size,w;//w表示该区间共安装了几个
    	int lazy;//lazy表示该区间是否全部安装或全部卸载
    	//1为全部安装,-1为全部卸载,0为无标记
    }tree[maxn<<2];
    void add(int a,int b){
    	e[++tot].next=head[a];
    	head[a]=tot;
    	e[tot].to=b;
    }
    void dfs(int u,int father){
    	fa[u]=father;
    	size[u]=1;
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa[u]) continue;
    		dep[v]=dep[u]+1;
    		dfs(v,u);
    		size[u]+=size[v];
    		if(!son[u]||size[v]>size[son[u]]) son[u]=v;
    	}
    }
    void get_top(int u,int t){
    	top[u]=t;
    	dfn[u]=++dfn_clock;
    	if(son[u]) get_top(son[u],t);
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa[u]||v==son[u]) continue;
    		get_top(v,v);
    	}
    }
    void build(int rt,int l,int r){
    	if(l>r) swap(l,r);
    	tree[rt].l=l,tree[rt].r=r,tree[rt].size=r-l+1;
    	if(l==r) return;
    	int mid=l+r>>1;
    	build(rt<<1,l,mid);
    	build(rt<<1|1,mid+1,r);
    }
    void renew(int rt){
    	tree[rt].w=tree[rt<<1].w+tree[rt<<1|1].w;
    }
    void push_down(int rt){//修改版push_down操作
    	if(tree[rt].lazy==1){
    		tree[rt<<1].w=tree[rt<<1].size;
    		tree[rt<<1|1].w=tree[rt<<1|1].size;
    		tree[rt<<1].lazy=1;
    		tree[rt<<1|1].lazy=1;
    	}
    	if(tree[rt].lazy==-1){
    		tree[rt<<1].w=0;
    		tree[rt<<1|1].w=0;
    		tree[rt<<1].lazy=-1;
    		tree[rt<<1|1].lazy=-1;
    	}
    	tree[rt].lazy=0;
    }
    void update(int rt,int s,int t,int mode){//mode即代表操作模式
    	if(s>t) swap(s,t);
    	if(s<=tree[rt].l&&t>=tree[rt].r){
    		tree[rt].lazy=mode;
    		if(mode==1) tree[rt].w=tree[rt].size;
    		if(mode==-1) tree[rt].w=0;
    		return;
    	}
    	push_down(rt);
    	int mid=tree[rt].l+tree[rt].r>>1;
    	if(s<=mid) update(rt<<1,s,t,mode);
    	if(t>mid) update(rt<<1|1,s,t,mode);
    	renew(rt);
    }
    int query(int rt,int s,int t){//查询[s,t]已安装的数量
    	if(s>t) swap(s,t);
    	int ans=0;
    	if(s<=tree[rt].l&&t>=tree[rt].r) return tree[rt].w;
    	push_down(rt);
    	int mid=tree[rt].l+tree[rt].r>>1;
    	if(s<=mid) ans+=query(rt<<1,s,t);
    	if(t>mid) ans+=query(rt<<1|1,s,t);
    	return ans;
    }
    int ask(int u){//树上查询u到根之间已安装数
    	int ans=0;
    	while(top[u]){
    		ans+=query(1,dfn[top[u]],dfn[u]);
    		u=fa[top[u]];
    	}
    	ans+=query(1,1,dfn[u]);
    	return ans;
    }
    void treeadd(int u,int mode){//树上全部安装或卸载u到根之间全部软件
    	while(top[u]){
    		update(1,dfn[top[u]],dfn[u],mode);
    		u=fa[top[u]];
    	}
    	update(1,1,dfn[u],mode);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<n;i++){
    		int tmp;
    		scanf("%d",&tmp);
    		add(i,tmp),add(tmp,i);
    	}
    	dfs(0,0);
    	get_top(0,0);
    	build(1,1,n);
    	scanf("%d",&q);
    	while(q--){
    		char s[10];int x;
    		scanf("%s%d",s,&x);
    		if(s[0]=='i'){
    			printf("%d
    ",dep[x]+1-ask(x));
    			treeadd(x,1);
    		}
    		else{
    			printf("%d
    ",query(1,dfn[x],dfn[x]+size[x]-1));
    			update(1,dfn[x],dfn[x]+size[x]-1,-1);
    		}
    	}
    	return 0;
    }
    

    幸甚至哉,歌以咏志。

  • 相关阅读:
    P2610 [ZJOI2012]旅游
    P2323 [HNOI2006]公路修建问题
    P3629 [APIO2010]巡逻
    ARC059F
    AGC004D Teleporter
    p3203 弹飞绵羊
    bzoj5450 轰炸
    bzoj4313 三维积木
    cf123E Maze
    bzoj4423 [AMPPZ2013]Bytehattan
  • 原文地址:https://www.cnblogs.com/DarthVictor/p/13417793.html
Copyright © 2011-2022 走看看