zoukankan      html  css  js  c++  java
  • P2486 [SDOI2011]染色

    链接

    调了好久。。。

    我平常写平衡树时 (push) (tag) 的操作都习惯把 (rev) 数组清零,但在 (LCT) 中不行,因为 (rev) 储存了节点间的父子关系,直接清零会改变树的结构。

    (frak{code})

    #include<bits/stdc++.h>
    #define IL inline
    #define LL long long
    #define ls(x) ch[x][0]
    #define rs(x) ch[x][1]
    using namespace std;
    const int N=1e5+3;
    int n,m;
    IL int in(){
    	char c;int f=1;
    	while((c=getchar())<'0'||c>'9')
    		if(c=='-') f=-1;
    	int x=c-'0';
    	while((c=getchar())>='0'&&c<='9')
    		x=x*10+c-'0';
    	return x*f;
    }
    struct LCT{
    	int fa[N],ch[N][2],rev[N],tag[N],col[N],lc[N],rc[N],sum[N];
    	IL int chk(int x){return rs(fa[x])==x;}
    	IL int noroot(int x){return ls(fa[x])==x||rs(fa[x])==x;}
    	IL void pushup(int x){
    		if(ls(x)) lc[x]=lc[ls(x)];else lc[x]=col[x];
    		if(rs(x)) rc[x]=rc[rs(x)];else rc[x]=col[x];
    		sum[x]=sum[ls(x)]+sum[rs(x)]+1;
    		if(ls(x)) sum[x]-=(col[x]==rc[ls(x)]);
    		if(rs(x)) sum[x]-=(col[x]==lc[rs(x)]);
    	}
    	IL void Rev(int x){rev[x]^=1,swap(ls(x),rs(x)),swap(lc[x],rc[x]);}
    	IL void Tag(int x,int v){tag[x]=col[x]=lc[x]=rc[x]=v,sum[x]=1;}
    	IL void pushdown(int x){
    		if(tag[x]){
    			if(ls(x)) Tag(ls(x),tag[x]);
    			if(rs(x)) Tag(rs(x),tag[x]);
    			tag[x]=0;
    		}
    		if(rev[x]){
    			if(ls(x)) Rev(ls(x));
    			if(rs(x)) Rev(rs(x));
    			rev[x]=0;
    		}
    	}
    	IL void rotate(int x){
    		int y=fa[x],z=fa[y],k=chk(x),w=ch[x][k^1];
    		if(noroot(y)) ch[z][chk(y)]=x;
    		if(w) fa[w]=y;
    		fa[y]=x,fa[x]=z,ch[x][k^1]=y,ch[y][k]=w;
    		pushup(y),pushup(x);
    	}
    	void pushall(int x){
    		if(noroot(x)) pushall(fa[x]);
    		pushdown(x);
    	}
    	IL void splay(int x){
    		pushall(x);
    		while(noroot(x)){
    			int y=fa[x];
    			if(noroot(y))
    				rotate(chk(x)^chk(y)?x:y);
    			rotate(x);
    		}
    	}
    	IL void access(int x){for(int y=0;x;x=fa[y=x]) splay(x),rs(x)=y,pushup(x);}
    	IL void makeroot(int x){access(x),splay(x),Rev(x);}
    	IL void split(int x,int y){makeroot(x),access(y),splay(y);}
    	IL void link(int x,int y){makeroot(x),fa[x]=y;}
    }T;
    int main()
    {
    	char op[5];int x,y,z;
    	n=in(),m=in();
    	for(int i=1;i<=n;++i) T.col[i]=T.lc[i]=T.rc[i]=in(),T.sum[i]=1;
    	for(int i=1;i<n;++i) T.link(in(),in());
    	while(m--){
    		scanf("%s",op+1),x=in(),y=in();
    		if(op[1]=='Q') T.split(x,y),printf("%d
    ",T.sum[y]);
    		else T.split(x,y),T.Tag(y,in());
    	}
    	return 0;
    } 
    

    附上一年多前写的树剖代码(那时真的 (naive),代码好笨拙啊qwq

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    struct hh{
    	int next,to;
    }lin[maxn<<1];
    struct kk{
    	int left,right,num;
    }a[maxn<<2];
    int siz[maxn],fa[maxn],d[maxn],son[maxn],numm[maxn];
    int top[maxn],seg[maxn],rev[maxn],fir[maxn],nn,n,m,ans,z,last[4][3];
    char sign[maxn<<2];
    inline int read()
    {
    	char c;
    	while((c=getchar())<'0'||c>'9');
    	int x=c-'0';
    	while((c=getchar())>='0'&&c<='9')
    	  x=x*10+c-'0';
    	return x;  
    }
    void init(int x,int y)
    {
    	lin[++nn].next=fir[x];
    	fir[x]=nn;
    	lin[nn].to=y;
    }
    void dfs1(int s,int f)
    {
    	int u;
    	siz[s]=1,d[s]=d[f]+1,fa[s]=f;
    	for(int i=fir[s];i;i=lin[i].next)
    	{
    		u=lin[i].to;
    		if(u!=f){
    	  	dfs1(u,s);
    	  	siz[s]+=siz[u];
    	  	if(siz[u]>siz[son[s]]) son[s]=u;
    	  }
    	} 
    }
    void dfs2(int f)
    {
    	int u=son[f];
    	if(u){
    		seg[u]=++seg[0];
    		rev[seg[0]]=u;
    		top[u]=top[f];
    		dfs2(u);
    	}
    	for(int i=fir[f];i;i=lin[i].next)
    	{
    		u=lin[i].to;
    		if(!top[u]){
    	  	seg[u]=++seg[0];
    	  	rev[seg[0]]=u;
    	  	top[u]=u;
    	  	dfs2(u);
    	  }
    	}
    }
    void pd(int k)
    {
    	a[k].left=a[k<<1].left,a[k].right=a[k<<1|1].right;
    	a[k].num=a[k<<1].num+a[k<<1|1].num;
    	if(a[k<<1].right==a[k<<1|1].left) --a[k].num;
    }
    void build(int k,int l,int r)
    {
    	if(l==r){
    		a[k].left=a[k].right=numm[rev[l]],a[k].num=1;return;
    	}
    	int mid=l+r>>1;
    	build(k<<1,l,mid),build(k<<1|1,mid+1,r);
    	pd(k);
    }
    void push(int k)
    {
    	a[k<<1].left=a[k<<1].right=a[k<<1|1].left=a[k<<1|1].right=a[k].left;
    	a[k<<1].num=a[k<<1|1].num=1;sign[k]=0,sign[k<<1]=sign[k<<1|1]=1;
    }
    void query(int k,int l,int r,int ll,int rr)
    {
    	if(l>=ll&&r<=rr){
    		ans+=a[k].num;
    		if(l==ll) last[3][nn]=a[k].left;//fx
    		if(r==rr) last[2][nn]=a[k].right;//x
    		return;
    	}
    	if(sign[k]) push(k);
    	int mid=l+r>>1;
    	if(mid>=ll) query(k<<1,l,mid,ll,rr);
    	if(mid<rr) query(k<<1|1,mid+1,r,ll,rr);
    	if(mid>=ll&&mid<rr&&a[k<<1].right==a[k<<1|1].left) ans--; 
    } 
    void change(int k,int l,int r,int ll,int rr)
    {
    	if(l>=ll&&r<=rr){
    		a[k].num=1,a[k].left=a[k].right=z,sign[k]=1;return;
    	}
    	if(sign[k]) push(k);
    	int mid=l+r>>1;
    	if(mid>=ll) change(k<<1,l,mid,ll,rr);
    	if(mid<rr) change(k<<1|1,mid+1,r,ll,rr);
    	pd(k);
    }
    void ask(int x,int y)
    {
    	int fx=top[x],fy=top[y];
    	last[1][1]=last[1][2]=-1;
    	while(fx!=fy)
    	{
    		if(d[fx]>d[fy]){
    			nn=1,query(1,1,seg[0],seg[fx],seg[x]);
    			if(last[1][1]==last[2][1]) ans--;
    			last[1][1]=last[3][1];
    			x=fa[fx],fx=top[x];
    		}
    		else{
    			nn=2,query(1,1,seg[0],seg[fy],seg[y]);
    			if(last[1][2]==last[2][2]) ans--;
    			last[1][2]=last[3][2];
    			y=fa[fy],fy=top[y];
    		}
    	}
    	nn=2;
    	if(d[x]>d[y]) swap(x,y),nn=1;
    	query(1,1,seg[0],seg[x],seg[y]);
    	if(last[1][nn]==last[2][nn]) ans--;
    	if(last[3][nn]==last[1][3-nn]) ans--;
    }
    void solve(int x,int y)
    {
    	int fx=top[x],fy=top[y];
    	while(fx!=fy){
    		if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
    		change(1,1,seg[0],seg[fx],seg[x]);
    		x=fa[fx],fx=top[x];
    	}
    	if(d[x]>d[y]) swap(x,y);
    	change(1,1,seg[0],seg[x],seg[y]);
    }
    int main()
    {
    	int x,y;
    	char flag[5];
    	n=read(),m=read();
    	for(int i=1;i<=n;++i) numm[i]=read();
    	for(int i=1;i<n;++i)
    	{
    		x=read(),y=read();
    		init(x,y),init(y,x);
    	}
    	dfs1(1,0),seg[0]=seg[1]=rev[1]=top[1]=1,dfs2(1),build(1,1,seg[0]);
    	while(m--)
    	{
    		scanf("%s",flag);
    		if(flag[0]=='Q'){
    			x=read(),y=read(),ans=0,ask(x,y),printf("%d
    ",ans);
    		}
    		else{
    			x=read(),y=read(),z=read(),solve(x,y);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    DS博客作业05--查找
    DS博客作业04--图
    DS博客作业03--树
    DS博客作业02--栈和队列
    C博客作业05-指针
    C语言——数组博客作业
    c语言博客3—函数
    循环结构博客
    c语言博客,顺序与分支结构
    Java面向对象课程设计——购物车
  • 原文地址:https://www.cnblogs.com/yiqiAtiya/p/14259531.html
Copyright © 2011-2022 走看看