• BZOJ2243: [SDOI2011]染色


    BZOJ2243: [SDOI2011]染色

    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<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

    题解Here!

    树上操作,首选 树链剖分/LCT。

    这题就只有10w,所以树剖即可。

    线段树维护:区间颜色数,区间左右颜色。

    上传时:直接加,如果 左区间的右颜色==右区间的左颜色,颜色数-1。

    标记下传:直接左右颜色修改,颜色数赋为1。

    记得在跳树链时判断一下起始节点的颜色是否要合并。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define DATA(x) b[x].data
    #define DATAL(x) b[x].left
    #define DATAR(x) b[x].right
    #define SIGN(x) b[x].c
    #define LSIDE(x) b[x].l
    #define RSIDE(x) b[x].r
    #define MAXN 100010
    using namespace std;
    int n,m,c=1,d=1;
    int val[MAXN],head[MAXN],id[MAXN],top[MAXN],deep[MAXN],son[MAXN],fa[MAXN],size[MAXN];
    struct node1{
    	int next,to;
    }a[MAXN<<1];
    struct node2{
    	int data,left,right,c;
    	int l,r;
    }b[MAXN<<2];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    void add(int u,int v){
    	a[c].to=v;
    	a[c].next=head[u];
    	head[u]=c++;
    	a[c].to=u;
    	a[c].next=head[v];
    	head[v]=c++;
    }
    void dfs1(int rt){
    	son[rt]=0;size[rt]=1;
    	for(int i=head[rt];i;i=a[i].next){
    		int will=a[i].to;
    		if(!deep[will]){
    			deep[will]=deep[rt]+1;
    			fa[will]=rt;
    			dfs1(will);
    			size[rt]+=size[will];
    			if(size[will]>size[son[rt]])son[rt]=will;
    		}
    	}
    }
    void dfs2(int rt,int f){
    	id[rt]=d++;top[rt]=f;
    	if(son[rt])dfs2(son[rt],f);
    	for(int i=head[rt];i;i=a[i].next){
    		int will=a[i].to;
    		if(will!=son[rt]&&will!=fa[rt])
    		dfs2(will,will);
    	}
    }
    void pushup(int rt){
    	DATAL(rt)=DATAL(LSON);DATAR(rt)=DATAR(RSON);
    	DATA(rt)=DATA(LSON)+DATA(RSON);
    	if(DATAR(LSON)==DATAL(RSON))DATA(rt)--;
    }
    void pushdown(int rt){
    	if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return;
    	SIGN(LSON)=DATAL(LSON)=DATAR(LSON)=SIGN(rt);
    	DATA(LSON)=1;
    	SIGN(RSON)=DATAL(RSON)=DATAR(RSON)=SIGN(rt);
    	DATA(RSON)=1;
    	SIGN(rt)=0;
    }
    void buildtree(int l,int r,int rt){
    	int mid;
    	LSIDE(rt)=l;
    	RSIDE(rt)=r;
    	if(l==r){
    		DATA(rt)=0;
    		return;
    	}
    	mid=l+r>>1;
    	buildtree(l,mid,LSON);
    	buildtree(mid+1,r,RSON);
    	pushup(rt);
    }
    void update(int l,int r,int c,int rt){
    	int mid;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
    		SIGN(rt)=DATAL(rt)=DATAR(rt)=c;
    		DATA(rt)=1;
    		return;
    	}
    	pushdown(rt);
    	mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)update(l,r,c,LSON);
    	if(mid<r)update(l,r,c,RSON);
    	pushup(rt);
    }
    int query(int l,int r,int rt){
    	int mid,ans=0;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
    	return DATA(rt);
    	pushdown(rt);
    	mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)ans+=query(l,r,LSON);
    	if(mid<r)ans+=query(l,r,RSON);
    	if(l<=mid&&mid<r&&DATAR(LSON)==DATAL(RSON))ans--;
    	return ans;
    }
    int qcolour(int l,int r,int rt){
    	int mid;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
    	return DATAL(rt);
    	pushdown(rt);
    	mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)return qcolour(l,r,LSON);
    	else return qcolour(l,r,RSON);
    }
    void work1(int x,int y,int z){
    	while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]])swap(x,y);
    		update(id[top[x]],id[x],z,1);
    		x=fa[top[x]];
    	}
    	if(deep[x]>deep[y])swap(x,y);
    	update(id[x],id[y],z,1);
    	return;
    }
    void work2(int x,int y){
    	int s=0,left,right;
    	while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]])swap(x,y);
    		s+=query(id[top[x]],id[x],1);
    		left=qcolour(id[top[x]],id[top[x]],1);
    		right=qcolour(id[fa[top[x]]],id[fa[top[x]]],1);
    		x=fa[top[x]];
    		if(left==right)s--;
    	}
    	if(deep[x]>deep[y])swap(x,y);
    	s+=query(id[x],id[y],1);
    	printf("%d
    ",s==0?1:s);
    	return;
    }
    void work(){
    	char ch[2];
    	int x,y,z;
    	while(m--){
    		scanf("%s",ch);x=read();y=read();
    		if(ch[0]=='C'){
    			z=read();
    			work1(x,y,z);
    		}
    		if(ch[0]=='Q')work2(x,y);
    	}
    }
    void init(){
    	int u,v;
    	n=read();m=read();
    	for(int i=1;i<=n;i++)val[i]=read();
    	for(int i=1;i<n;i++){
    		u=read();v=read();
    		add(u,v);
    	}
    	deep[1]=fa[1]=1;
    	dfs1(1);
    	dfs2(1,1);
    	buildtree(1,n,1);
    	for(int i=1;i<=n;i++)update(id[i],id[i],val[i],1);
    }
    int main(){
    	init();
    	work();
    	return 0;
    }
    
  • 相关阅读:
    链路追踪
    Zuul网关
    MyBatis批量插入
    自定义组件使用v-model
    正则表达式入门
    博客园主题1【备份】
    关于我
    input输入框内容规范正则总结
    实例003:完全平方数
    python基础day5dict
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9031245.html
Copyright © 2020-2023  润新知