zoukankan      html  css  js  c++  java
  • #树链剖分,线段树#洛谷 2486 [SDOI2011]染色

    题目


    分析

    就是把维护颜色段和树结合起来,

    注意拼接的时候要减去中间相同的部分


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=100011; struct node{int y,next;}e[N<<1];
    int dep[N],as[N],fat[N],top[N],dfn[N],tot,son[N],n,Lc,Rc,lL,rR,m;
    int col[N],nfd[N],big[N],w[N<<2],lazy[N<<2],lc[N<<2],rc[N<<2],k=1;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(int ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    inline void add(int x,int y){
        e[++k]=(node){y,as[x]},as[x]=k,
        e[++k]=(node){x,as[y]},as[y]=k;
    }
    inline void pup(int k){
    	lc[k]=lc[k<<1],rc[k]=rc[k<<1|1];
    	w[k]=w[k<<1]+w[k<<1|1]-(rc[k<<1]==lc[k<<1|1]);
    }
    inline void pdown(int k){
    	lc[k<<1]=lc[k<<1|1]=lc[k],lazy[k<<1]=lazy[k<<1|1]=1,
    	rc[k<<1]=rc[k<<1|1]=rc[k],w[k<<1]=w[k<<1|1]=1,lazy[k]=0;
    }
    inline void build(int k,int l,int r){
    	if (l==r){
    		lc[k]=rc[k]=col[nfd[l]],w[k]=1;
    		return;
    	}
    	rr int mid=(l+r)>>1;
    	build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
    	pup(k);
    }
    inline void update(int k,int l,int r,int x,int y,int z){
    	if (l==x&&r==y){
    		lc[k]=rc[k]=z,w[k]=lazy[k]=1;
    		return;
    	}
    	if (lazy[k]) pdown(k);
    	rr int mid=(l+r)>>1;
    	if (y<=mid) update(k<<1,l,mid,x,y,z);
    	    else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
    	        else update(k<<1,l,mid,x,mid,z),
    			    update(k<<1|1,mid+1,r,mid+1,y,z);
    	pup(k);
    }
    inline signed query(int k,int l,int r,int x,int y){
    	if (l==x&&r==y){
    		if (l==lL) Lc=lc[k];
    		if (r==rR) Rc=rc[k];
    		return w[k];
    	}
    	if (lazy[k]) pdown(k);
    	rr int mid=(l+r)>>1;
    	if (y<=mid) return query(k<<1,l,mid,x,y);
    	    else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
    	        else {
    	        	rr int ansL=query(k<<1,l,mid,x,mid),
    	        	    ansR=query(k<<1|1,mid+1,r,mid+1,y);
    	        	return ansL+ansR-(rc[k<<1]==lc[k<<1|1]);
    			}
    }
    inline void dfs1(int x,int fa){
    	dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
    	for (rr int i=as[x],mson=-1;i;i=e[i].next)
    	if (e[i].y!=fa){
    		dfs1(e[i].y,x);
    		son[x]+=son[e[i].y];
    		if (son[e[i].y]>mson) big[x]=e[i].y,mson=son[e[i].y];
    	}
    }
    inline void dfs2(int x,int linp){
    	dfn[x]=++tot,nfd[tot]=x,top[x]=linp;
    	if (!big[x]) return; dfs2(big[x],linp);
    	for (rr int i=as[x];i;i=e[i].next)
    	if (e[i].y!=fat[x]&&e[i].y!=big[x]) dfs2(e[i].y,e[i].y);
    }
    inline void Update(int x,int y,int z){
    	for (;top[x]!=top[y];x=fat[top[x]]){
    		if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
    		update(1,1,n,dfn[top[x]],dfn[x],z);
    	}
    	if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
    	update(1,1,n,dfn[x],dfn[y],z);
    }
    inline signed Query(int x,int y){
    	int ans=0,xLc=-1,yLc=-1;
    	for (;top[x]!=top[y];x=fat[top[x]]){
    		if (dep[top[x]]<dep[top[y]]){
    		    x^=y,y^=x,x^=y;
    			if (xLc^yLc) xLc^=yLc,yLc^=xLc,xLc^=yLc;		    
    		}
    		lL=dfn[top[x]],rR=dfn[x];
    		ans+=query(1,1,n,dfn[top[x]],dfn[x]);
    		ans-=(Rc==xLc),xLc=Lc;
    	}
    	if (dep[x]<dep[y]){
    	    x^=y,y^=x,x^=y;
    	    if (xLc^yLc) xLc^=yLc,yLc^=xLc,xLc^=yLc;
    	}
    	lL=dfn[y],rR=dfn[x];
    	ans+=query(1,1,n,dfn[y],dfn[x]);
    	ans-=(Rc==xLc)+(Lc==yLc);//除了x的拼接还有y的拼接
    	return ans;
    }
    signed main(){
    	n=iut(); m=iut();
    	for (rr int i=1;i<=n;++i) col[i]=iut();
    	for (rr int i=1;i<n;++i) add(iut(),iut());
    	dfs1(1,0),dfs2(1,1),build(1,1,n);
    	for (;m;--m){
    		rr char c=getchar();
    		while (c!='C'&&c!='Q') c=getchar();
    		rr int x=iut(),y=iut();
    		if (c=='C') Update(x,y,iut());
    		    else print(Query(x,y)),putchar(10);
    	}
        return 0;
    }
    
  • 相关阅读:
    Fragment传参
    android手机旋转方向识别
    如何激活已经运行过的Activity, 而不是重新启动新的Activity
    Android 在Canvas中实现画笔效果(一)--钢笔
    [AS3]as3画笔实例实现橡皮擦功能源代码
    在 Windows 環境下利用 VNC 遠端控管 Mac OS X Server
    mac下开发IOS代码管理
    Android开发--仿微信语音对讲录音
    Android 二维码 生成和识别(附Demo源码)
    Android开源项目分类汇总
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13921970.html
Copyright © 2011-2022 走看看