zoukankan      html  css  js  c++  java
  • CF1017G 【The Tree】

    Linker

    做法:树链剖分+线段树

    首先(O(n^2))的暴力还是挺好想的,就不多阐述了。

    然后看没有2操作的该怎么写。

    当没有2操作的时候,我们可以通过一种特殊的形式来记录点的染色:通过给这个点加权值。

    假设x是y的祖先,若x可以影响到y的话,不难发现,需要满足的性质就是 (x o y ext{这一段路上的总权值}>=dep[x]-dep[y]+1)

    记录这一段路上的总权值为(dis),移项得到 (dis+dep[x]>=dep[y]+1)

    利用线段树维护(dis+dep[x]),然后对于向上跳的过程直接树链剖分向上跳。

    也就是说通过树链剖分+线段树就能写出来。这里代码就不放出来了。

    再看如果有了2操作我们该如何写。

    首先把这一整课子树清空是肯定要的。

    然后就看如果祖先的(dis)的影响到了下面的节点该如何操作。

    再来看看刚刚的式子 : (dis+dep[x]>=dep[y]+1)

    我们发现可以找到x的祖先的(dis+dep)最大值(其实就是再往上跳一遍),也会影响到他的子树(虽然说子树的每个点的(dis+dep)已经清零了,但是还是可以从上面转移下来)

    于是我们找到这个值以后,再让x的权值减去它就好了(相当于差分)

    //代码很丑,勿喷
    #include<bits/stdc++.h>
    #define re register
    #define rep(i,a,b) for(re int i=a,i##end=b; i<=i##end; i++)
    #define drep(i,a,b) for(re int i=a,i##end=b; i>=i##end; i--)
    #define repp(i,a,b) for(re int i=a,i##end=b; i<i##end; i++)
    #define drepp(i,a,b) for(re int i=a,i##end=b; i>i##end; i--)
    #define Erep(i,x) for(re int i=head[x]; i; i=Edge[i].nxt)
    #define lowbit(x) ((x)&-(x))
    #define debug(x) cerr<<#x<<" = "<<x<<endl
    #define ms(x,a) memset(x,a,sizeof x)
    #define PII pair<int,int>
    #define PLL pair<ll,ll>
    #define fi first
    #define se second
    #define coint const int
    #define coll const ll
    #define CM cerr<<(&S2-&S1)/1024./1024.<<"MB"<<endl
    typedef long long ll;
    using namespace std;
    template<class T>inline T rd(){
    	static char ch;static bool neg;static T x;
    	for(ch=0, neg=0; ch>'9'||ch<'0'; neg|=(ch=='-'),ch=getchar());
    	for(x=0; ch>='0'&&ch<='9'; x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar());
    	return neg?-x:x;
    }
    template<class T>inline T Max(const T &x, const T &y) { return x>y?x:y; }
    template<class T>inline T Min(const T &x, const T &y) { return x<y?x:y; }
    
    coint N=100000+5,M=200000+5;
    struct edge{
    	int to,nxt;
    }Edge[N<<1];
    int head[N],tcnt;
    inline void AddEdge(coint u, coint v){
    	Edge[++tcnt]=(edge)<%v,head[u]%>;
    	head[u]=tcnt; return;
    }
    
    struct Ask{
    	int opt,x;
    	inline void read() { opt=rd<int>(); x=rd<int>(); return; }
    }ask[M];
    
    int n,m;
    
    int dep[N],f[N],sz[N],son[N],top[N],L[N],R[N],ID[N],dfn;
    
    void pre_dfs(coint x, coint fa){
    	int &SZ=sz[x],&SON=son[x]; SZ=1;
    	Erep(i,x){
    		int y=Edge[i].to;
    		if(y==fa) continue;
    		dep[y]=dep[x]+1; f[y]=x;
    		pre_dfs(y,x);
    		SZ+=sz[y];
    		SON=(sz[SON]<sz[y]?y:SON);
    	}
    	return;
    }
    
    void dfs_top(coint x, coint fa, coint tp){
    	top[x]=tp; L[x]=++dfn; ID[dfn]=x;
    	coint &SON=son[x];
    	if(SON) dfs_top(SON,x,tp);
    	Erep(i,x){
    		int y=Edge[i].to;
    		if(y==fa || y==SON) continue;
    		dfs_top(y,x,y);
    	} R[x]=dfn;
    	return;
    }
    
    struct node{
    	int sum,mx;
    	friend node operator + (const node &x, const node &y){
    		return (node)<%x.sum+y.sum,Max(x.mx+y.sum,y.mx)%>;
    	}
    };
    
    struct Segment_Tree{
    	node sum[N<<2];
    	int lazy[N<<2];
    	inline void Up(coint p){
    		coint ls=p<<1,rs=ls|1;
    		sum[p]=sum[ls]+sum[rs];
    		return;
    	}
    	inline void Down(coint p){
    		int &x=lazy[p];
    		if(!x) return;
    		coint ls=p<<1,rs=ls|1;
    		lazy[ls]=lazy[rs]=1;
    		sum[ls]=sum[rs]=(node)<%0,0%>;
    		x=0; return;
    	}
    	void Build(coint p, coint l, coint r){
    		sum[p]=(node)<%0,0%>; lazy[p]=0;
    		if(l==r) return;
    		coint mid=(l+r)>>1,ls=p<<1,rs=ls|1;
    		Build(ls,l,mid); Build(rs,mid+1,r);
    		return;
    	}
    	void Upd1(coint p, coint l, coint r, coint L, coint R){
    		if(l==L && r==R){
    			sum[p]=(node)<%0,0%>;
    			lazy[p]=1;
    			return;
    		}
    		Down(p);
    		coint mid=(l+r)>>1,ls=p<<1,rs=ls|1;
    		if(R<=mid) Upd1(ls,l,mid,L,R);
    		else if(L>mid) Upd1(rs,mid+1,r,L,R);
    		else Upd1(ls,l,mid,L,mid),Upd1(rs,mid+1,r,mid+1,R);
    		Up(p); return;
    	}
    	void Upd2(coint p, coint l, coint r, coint x, coint val){
    		if(l==r){
    			sum[p]=(node)<%val,dep[ID[l]]+val%>;
    			return;
    		}
    		Down(p);
    		coint mid=(l+r)>>1,ls=p<<1,rs=ls|1;
    		if(x<=mid) Upd2(ls,l,mid,x,val);
    		else Upd2(rs,mid+1,r,x,val);
    		Up(p); return;
    	}
    	node Que(coint p, coint l, coint r, coint L, coint R){
    		if(l==L && r==R) return sum[p];
    		Down(p);
    		coint mid=(l+r)>>1,ls=p<<1,rs=ls|1;
    		if(R<=mid) return Que(ls,l,mid,L,R);
    		if(L>mid) return Que(rs,mid+1,r,L,R);
    		return Que(ls,l,mid,L,mid)+Que(rs,mid+1,r,mid+1,R);
    	}
    }sgtr;
    
    inline int Get_Max(int x){
    	node res=(node)<%0,0%>;
    	int tpx=top[x];
    	while(x){
    		res=sgtr.Que(1,1,n,L[tpx],L[x])+res;
    		x=f[tpx]; tpx=top[x];
    	}
    	return res.mx;
    }
    
    inline void solve(){
    	pre_dfs(1,0); dfs_top(1,0,1);
    	rep(i,1,m){
    		coint opt=(ask[i].opt),x=ask[i].x;
    		switch(opt){
    			case 1:{
    				sgtr.Upd2(1,1,n,L[x],sgtr.Que(1,1,n,L[x],L[x]).sum+1);
    				break;
    			}
    			case 2:{
    				sgtr.Upd1(1,1,n,L[x],R[x]);
    				int tmp=Get_Max(x);
    				if(tmp>=dep[x]+1) sgtr.Upd2(1,1,n,L[x],dep[x]-tmp);
    				break;
    			}
    			default:{
    				puts(Get_Max(x)>=dep[x]+1?"black":"white");
    				break;
    			}
    		}
    	}
    	return;
    }
    
    
    int main(){
    	n=rd<int>(),m=rd<int>();
    	rep(i,2,n){
    		int x=rd<int>();
    		AddEdge(x,i); AddEdge(i,x);
    	}
    	rep(i,1,m) ask[i].read();
    	solve();
    	return 0;
    }
    
    
  • 相关阅读:
    Windows Server 2003 SP2(32位) 中文版 下载地址 光盘整合方法
    用Recycle()方法对Java对象的重要性
    Lotus中千奇百怪的 $$
    Developing a simple application using steps "User Decision" and "Mail"(1) 沧海
    沟通中的情绪管理(演讲稿) 沧海
    人只有在压力之下,才可能成功,没做一件事,都必须成功,不许言败 沧海
    什么是IDOC,以及IDOC的步骤 沧海
    VS2008 Professional Edition CHS中的deffactory.dat读取错误 沧海
    Including custom text in the step "User Decision" 沧海
    SAP Upgrade Strategy 沧海
  • 原文地址:https://www.cnblogs.com/ppp204-is-a-VC/p/11836635.html
Copyright © 2011-2022 走看看