zoukankan      html  css  js  c++  java
  • [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]之间。

    solution

    (LCT),挺板子的,记录区间的左右端点的颜色,然后注意(reverse)的时候要(swap(lcol,rcol))

    树链剖分也可以写,应该会快一些?但是复杂度高

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 1e5+1;
    
    int col[maxn];
    
    struct Link_Cut_Tree {
    	int fa[maxn],son[maxn][2],lcol[maxn],rcol[maxn],rev[maxn],cov[maxn],sum[maxn],sta[maxn];
    	void update(int x) {
    		lcol[x]=son[x][0]?lcol[son[x][0]]:col[x];
    		rcol[x]=son[x][1]?rcol[son[x][1]]:col[x];
    		if(son[x][0]&&son[x][1]) sum[x]=sum[son[x][0]]+sum[son[x][1]]+1-(col[x]==rcol[son[x][0]])-(col[x]==lcol[son[x][1]]);
    		else if(son[x][0]) sum[x]=sum[son[x][0]]+(col[x]!=rcol[son[x][0]]);
    		else if(son[x][1]) sum[x]=sum[son[x][1]]+(col[x]!=lcol[son[x][1]]);
    		else sum[x]=1;
    	}
    	void push_rev(int x) {if(x) rev[x]^=1,swap(son[x][0],son[x][1]),swap(lcol[x],rcol[x]);}
    	void push_cov(int x,int c) {if(x) col[x]=cov[x]=lcol[x]=rcol[x]=c,sum[x]=1;}
    	void pushdown(int x) {
    		if(rev[x]) rev[x]^=1,push_rev(son[x][0]),push_rev(son[x][1]);
    		if(cov[x]) push_cov(son[x][0],cov[x]),push_cov(son[x][1],cov[x]),cov[x]=0;
    	}
    	int which(int x) {return son[fa[x]][1]==x;}
    	int is_root(int x) {return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
    	void rotate(int x) {
    		int f=fa[x],ff=fa[f],w=which(x);
    		if(!is_root(f)) son[ff][son[ff][1]==f]=x;
    		fa[x]=ff,fa[f]=x,son[f][w]=son[x][w^1],fa[son[x][w^1]]=f,son[x][w^1]=f;
    		update(f),update(x);
    	}
    	void splay(int x) {
    		int t=x,top=0;
    		while(!is_root(t)) sta[++top]=t,t=fa[t];sta[++top]=t;
    		while(top) pushdown(sta[top--]);
    		while(!is_root(x)) {
    			int y=fa[x],z=fa[y];
    			if(!is_root(y)) rotate(((son[y][1]==x)^(son[z][1]==y))?x:y);
    			rotate(x);
    		}update(x);
    	}
    	void access(int x) {
    		for(int t=0;x;t=x,x=fa[x]) splay(x),son[x][1]=t,update(x);
    	}
    	void make_root(int x) {
    		access(x),splay(x),push_rev(x);
    	}
    	void link(int x,int y) {
    		make_root(x),fa[x]=y;
    	}
    	void split(int x,int y) {
    		make_root(x),access(y),splay(y);
    	}
    	void modify(int x,int y,int c) {
    		split(x,y),push_cov(y,c);
    	}
    	int query(int x,int y) {
    		split(x,y);return sum[y];
    	}
    }LCT;
    
    int main() {
    	int n,m;read(n),read(m);
    	for(int i=1;i<=n;i++) read(col[i]);
    	for(int i=1,x,y;i<n;i++) read(x),read(y),LCT.link(x,y);
    	for(int i=1;i<=m;i++) {
    		char s[4];scanf("%s",s+1);int x,y,z;read(x),read(y);
    		if(s[1]=='C') read(z),LCT.modify(x,y,z);
    		else write(LCT.query(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    【转】angular通过$http与服务器通信
    【转】Angular运行原理揭秘 Part 1
    【转】 定义模板和服务
    【转】angular Ajax请求
    【转】AngularJS路由和模板
    算法之美--2.2 Array
    算法之美--2.2数组
    人工神经网络--ANN
    AVL树原理及实现 +B树
    学习计划 2016//11//28
  • 原文地址:https://www.cnblogs.com/hbyer/p/10142464.html
Copyright © 2011-2022 走看看