• CF1017G The Tree


    一棵树,每个点为黑点或白点。一开始全是白点。

    支持维护三个操作:1、把(x)子树中包含(x)的极大黑连通块找出来,把所有点儿子染黑(如果(x)为白色直接将(x)染成黑色)。2、将一棵子树染白。3、询问一个点的颜色。

    (n,Qle 10^5)


    考虑怎么处理第一个操作。

    假设没有操作二,每次在操作一中给(x)加一,考虑询问出黑点的条件。

    玩一下可以发现:(x)为黑点,当且仅当存在一个祖先(y),满足(val(y,x)ge dis(y,x))。右边移项过去,相当于每个节点一开始权值为(-1),询问的时候是询问根到(x)的最大后缀和,判断其是否大于等于(0)

    接下来的问题是处理第二个询问。直接算出(x)到祖先的最大后缀和,在(x)处抵消,然后给(x)的子树全部赋值为(-1)即可。


    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 100005
    #define INF 1000000000
    int n;
    struct EDGE{
    	int to;
    	EDGE *las;
    } e[N];
    int ne;
    EDGE *last[N];
    int fa[N],siz[N],dep[N],hs[N],top[N],in[N],out[N],nowdfn;
    void dfs1(int x){
    	siz[x]=1;
    	dep[x]=dep[fa[x]]+1;
    	for (EDGE *ei=last[x];ei;ei=ei->las){
    		dfs1(ei->to);
    		siz[x]+=siz[ei->to];
    		if (siz[ei->to]>siz[hs[x]])
    			hs[x]=ei->to;
    	}
    }
    void dfs2(int x,int t){
    	top[x]=t;
    	in[x]=++nowdfn;
    	if (hs[x]){
    		dfs2(hs[x],t);
    		for (EDGE *ei=last[x];ei;ei=ei->las)
    			if (ei->to!=hs[x])
    				dfs2(ei->to,ei->to);
    	}
    	out[x]=nowdfn;
    }
    struct info{int sum,mx;} s[N*4];
    info merge(info a,info b){return (info){a.sum+b.sum,max(a.mx+b.sum,b.mx)};}
    int tag[N*4];
    void init(int k,int l,int r){
    	if (l==r){
    		s[k]={-1,-1};
    		return;
    	}
    	int mid=l+r>>1;
    	init(k<<1,l,mid);
    	init(k<<1|1,mid+1,r);
    	s[k]=merge(s[k<<1],s[k<<1|1]);
    }
    void gt(int k,int len){
    	tag[k]=-1;
    	s[k]={-len,-1};
    }
    void pd(int k,int l,int r){
    	if (tag[k]==-1){
    		int mid=l+r>>1;
    		gt(k<<1,mid-l+1);
    		gt(k<<1|1,r-mid);
    		tag[k]=0;	
    	}
    }
    info res;
    void query(int k,int l,int r,int st,int en){
    	if (st<=l && r<=en){
    		res=merge(s[k],res);
    		return;
    	}
    	pd(k,l,r);
    	int mid=l+r>>1;
    	if (mid<en) query(k<<1|1,mid+1,r,st,en);
    	if (st<=mid) query(k<<1,l,mid,st,en);
    }
    void add(int k,int l,int r,int x,int c){
    	if (l==r){
    		s[k].sum+=c;
    		s[k].mx+=c;
    		return;
    	}
    	pd(k,l,r);
    	int mid=l+r>>1;
    	if (x<=mid) add(k<<1,l,mid,x,c);
    	else add(k<<1|1,mid+1,r,x,c);
    	s[k]=merge(s[k<<1],s[k<<1|1]);
    }
    void clear(int k,int l,int r,int st,int en){
    	if (st<=l && r<=en){
    		gt(k,r-l+1);
    		return;
    	}
    	pd(k,l,r);
    	int mid=l+r>>1;
    	if (st<=mid) clear(k<<1,l,mid,st,en);
    	if (mid<en) clear(k<<1|1,mid+1,r,st,en);
    	s[k]=merge(s[k<<1],s[k<<1|1]);
    }
    int sufmx(int x){
    	res={0,-INF};
    	for (;x;x=fa[top[x]])
    		query(1,1,n,in[top[x]],in[x]);
    	return res.mx;
    }
    int main(){ 
    //	freopen("in.txt","r",stdin);
    	int Q;
    	scanf("%d%d",&n,&Q);
    	for (int i=2;i<=n;++i){
    		scanf("%d",&fa[i]);
    		e[ne]={i,last[fa[i]]};
    		last[fa[i]]=e+ne++;
    	}
    	dfs1(1),dfs2(1,1);
    	init(1,1,n);
    	while (Q--){
    		int op,x;
    		scanf("%d%d",&op,&x);
    		if (op==1){
    			add(1,1,n,in[x],1);
    		}
    		else if (op==2){
    			int tmp=sufmx(x);
    			add(1,1,n,in[x],-tmp-1);
    			if (in[x]<out[x])
    				clear(1,1,n,in[x]+1,out[x]);
    		}
    		else{
    			int tmp=sufmx(x);
    			if (tmp>=0)
    				printf("black
    ");
    			else
    				printf("white
    ");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    嵌入式开发之zynq——zynq开发环境搭建
    嵌入式开发之zynq——赛灵思的一款两a9加一fpga芯片的开发板
    数据结构和算法的选择
    找工作看准网
    健康情感之招聘---图像算法工程师
    grafana 邮件报警
    ELK logstash邮件报警
    grafana + influxdb + telegraf
    centos 6.5 上安装使用upsource
    ELK 中的elasticsearch 集群的部署
  • 原文地址:https://www.cnblogs.com/jz-597/p/13950860.html
Copyright © 2020-2023  润新知