zoukankan      html  css  js  c++  java
  • bzoj2243: [SDOI2011]染色(树链剖分)

    www.cnblogs.com/shaokele/


    bzoj2243: [SDOI2011]染色##

      Time Limit: 20 Sec
      Memory Limit: 512 MB

    Description###

      给定一棵有n个节点的无根树和m个操作,操作有2类:
      1、将节点a到节点b路径上所有点都染成颜色c;
      2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
      请你写一个程序依次完成这m个操作。
     

    Input###

      第一行包含2个整数n和m,分别表示节点数和操作数;
      第二行包含n个正整数表示n个节点的初始颜色
      下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
      下面 行每行描述一个操作:
      “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
      “Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
     

    Output###

      对于每个询问操作,输出一行答案。
     

    Sample Input###

      6 5
      2 2 1 2 1 1
      1 2
      1 3
      2 4
      2 5
      2 6
      Q 3 5
      C 2 1 1
      Q 3 5
      C 5 1 2
      Q 3 5
     

    Sample Output###

      3
      1
      2
      

    HINT

      数N<=105,操作数M<=105,所有的颜色C为整数且在[0, 10^9]之间。
      

    题目地址:  bzoj2243: [SDOI2011]染色

    题目大意: 已经很简洁了

      

    题解:

      裸的树链剖分
      
      只是要记该段颜色段数,左端点颜色,右端点颜色这三个东西
      
      在合并的时候处理颜色要特别小心仔细
      
      具体看代码


    AC代码

    #include <cstdio> 
    #include <algorithm>
    using namespace std;
    const int N=1e5+5;
    int n,Q,cnt,num;
    int fc[N],a[N];
    int last[N],lazy[N<<2];
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    struct edge{
    	int to,next;
    }e[N<<1];
    struct note{
    	int lcol,rcol,val;
    }T[N<<2];
    void add_edge(int u,int v){
    	e[++cnt]=(edge){v,last[u]};last[u]=cnt;
    	e[++cnt]=(edge){u,last[v]};last[v]=cnt;
    }
    int fa[N],sz[N],dep[N],son[N];
    void dfs1(int u,int father){
    	fa[u]=father;sz[u]=1;
    	dep[u]=dep[father]+1;
    	for(int i=last[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==father)continue;
    		dfs1(v,u);
    		sz[u]+=sz[v];
    		if(sz[v]>sz[son[u]])son[u]=v;
    	}
    }
    int pos[N],top[N];
    void dfs2(int u,int chain){
    	top[u]=chain;
    	pos[u]=++num;
    	a[num]=fc[u]+1;
    	if(!son[u])return;
    	dfs2(son[u],chain);
    	for(int i=last[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v!=fa[u] && v!=son[u])
    			dfs2(v,v);
    	}
    }
    void pushup(int k){
    	T[k].lcol=T[k<<1].lcol;
    	T[k].rcol=T[k<<1|1].rcol;
    	T[k].val=T[k<<1].val+T[k<<1|1].val-(T[k<<1].rcol==T[k<<1|1].lcol);
    }
    void pushdown(int k){
    	if(lazy[k]){
    		T[k<<1].lcol=T[k<<1].rcol=lazy[k<<1]=lazy[k];T[k<<1].val=1;
    		T[k<<1|1].lcol=T[k<<1|1].rcol=lazy[k<<1|1]=lazy[k];T[k<<1|1].val=1;
    		lazy[k]=0;
    	}
    }
    void build(int k,int l,int r){
    	if(l==r){
    		T[k]=(note){a[l],a[l],1};
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
    	pushup(k);
    }
    void update(int k,int l,int r,int L,int R,int col){
    	if(l==L && R==r){
    		T[k]=(note){col,col,1};
    		lazy[k]=col;
    		return;
    	}
    	pushdown(k);
    	int mid=(l+r)>>1;
    	if(R<=mid)update(k<<1,l,mid,L,R,col);
    	else if(L>mid)update(k<<1|1,mid+1,r,L,R,col);
    	else update(k<<1,l,mid,L,mid,col),update(k<<1|1,mid+1,r,mid+1,R,col);
    	pushup(k);
    }
    void change(int a,int b,int col){
    	while(top[a]!=top[b]){
    		if(dep[top[a]]<dep[top[b]])swap(a,b);
    		update(1,1,n,pos[top[a]],pos[a],col);
    		a=fa[top[a]];
    	}
    	if(dep[a]>dep[b])swap(a,b);
    	update(1,1,n,pos[a],pos[b],col);
    }
    note query(int k,int l,int r,int L,int R){
    	if(l==L && R==r)return T[k];
    	pushdown(k);
    	int mid=(l+r)>>1;
    	if(R<=mid)return query(k<<1,l,mid,L,R);
    	else if(L>mid)return query(k<<1|1,mid+1,r,L,R);
    	else{
    		note res,Lnote,Rnote;
    		Lnote=query(k<<1,l,mid,L,mid);
    		Rnote=query(k<<1|1,mid+1,r,mid+1,R);
    		res.lcol=Lnote.lcol;
    		res.rcol=Rnote.rcol;
    		res.val=Lnote.val+Rnote.val-(Lnote.rcol==Rnote.lcol);
    		return res;
    	}
    }
    int solve(int a,int b){
    	int acol=-1,bcol=-1,res=0;
    	note now;
    	while(top[a]!=top[b]){
    		if(dep[top[a]]<dep[top[b]])swap(a,b),swap(acol,bcol);
    		now=query(1,1,n,pos[top[a]],pos[a]);
    		res+=now.val-(now.rcol==acol);
    		acol=now.lcol;a=fa[top[a]];
    	}
    	if(dep[a]>dep[b])swap(a,b),swap(acol,bcol);
    	now=query(1,1,n,pos[a],pos[b]);
    	res+=now.val-(now.lcol==acol)-(now.rcol==bcol);
    	return res;
    }
    int main(){
    	n=read();Q=read();
    	for(int i=1;i<=n;i++)fc[i]=read();
    	for(int i=1;i<n;i++){
    		int u=read(),v=read();
    		add_edge(u,v);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	build(1,1,n);
    	while(Q--){
    		scanf("
    ");
    		int x,y,col;
    		char op=getchar();
    		if(op=='Q'){
    			scanf("%d%d",&x,&y);
    			printf("%d
    ",solve(x,y));
    		}else{
    			scanf("%d%d%d",&x,&y,&col);
    			change(x,y,col+1);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    如何自己搭一个脚手架
    vue脚手架搭建流程
    深入浅出ES6教程『async函数』
    在微信小程序中使用 async/await
    理解 JavaScript 的 async/await
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/shaokele/p/9410479.html
Copyright © 2011-2022 走看看