HYSBZ—2243 染色(LCT動態樹)

給定一棵有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]之間。


LCT做法

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(x) tree[x].fa
#define REV(x) tree[x].rev
#define LC(x) tree[x].child[0]
#define RC(x) tree[x].child[1]
#define C(x) tree[x].color
#define L_c(x) tree[x].left_color
#define R_c(x) tree[x].right_color
#define Size 300010
using namespace std;
inline int read(){
	int sum=0,fg=1;char c=getchar();
	while(c<'0' || c>'9'){if(c=='-')fg=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*fg;
}
struct lct{
	int fa,child[2],rev,mark;
	int color,left_color,right_color,sum;
}tree[Size];
int be[Size],ne[Size],to[Size],e;
struct link_cut_tree{
	inline bool isroot(int x){
		return LC(F(x))!=x && RC(F(x))!=x;
	}
	inline void pushup(int x){
		tree[x].sum=tree[LC(x)].sum+tree[RC(x)].sum+1;
		if(LC(x)){
			L_c(x)=L_c(LC(x));
			tree[x].sum-=(R_c(LC(x))==C(x));
		}
		else L_c(x)=C(x);
		if(RC(x)){
			R_c(x)=R_c(RC(x));
			tree[x].sum-=(L_c(RC(x))==C(x));
		}
		else R_c(x)=C(x);
	}
	inline void make_color(int x,int color){
		C(x)=L_c(x)=R_c(x)=tree[x].mark=color;tree[x].sum=1;
	}
	inline void pushdown(int x){
		if(REV(x)){
			REV(x)^=1;REV(LC(x))^=1;REV(RC(x))^=1;
			swap(LC(LC(x)),RC(LC(x)));swap(L_c(LC(x)),R_c(LC(x)));
			swap(LC(RC(x)),RC(RC(x)));swap(L_c(RC(x)),R_c(RC(x)));
		}
		if(tree[x].mark){
			if(LC(x))make_color(LC(x),tree[x].mark);
			if(RC(x))make_color(RC(x),tree[x].mark);
			tree[x].mark=0;
		}
	}
	void Pushdown(int x){
		if(!isroot(x))Pushdown(F(x));
		pushdown(x);
	}
	inline void rotate(int x){
		int A=F(x),B=F(A);bool w=(RC(A)==x);
		if(!isroot(A)){
			if(LC(B)==A)LC(B)=x;
			else if(RC(B)==A)RC(B)=x;
		}
		F(tree[x].child[w^1])=A;F(A)=x;F(x)=B;
		tree[A].child[w]=tree[x].child[w^1];tree[x].child[w^1]=A;
		pushup(A);pushup(x);
	}
	inline void splay(int x){
		Pushdown(x);
		while(!isroot(x)){
			if(!isroot(F(x)))rotate(x);
			rotate(x);
		}
	}
	inline void access(int x){
		for(int i=0;x;i=x,x=F(x))splay(x),RC(x)=i,pushup(x);
	}
	inline int find_root(int x){
		access(x);splay(x);
		while(LC(x))x=LC(x);
		return x;
	}
	inline void reverse(int x){
		access(x);splay(x);REV(x)^=1;
		swap(LC(x),RC(x));swap(L_c(x),R_c(x));
	}
	inline void update(int x,int y,int w){
		reverse(x);access(y);splay(y);
		make_color(y,w);
	}
	inline int query(int x,int y){
		reverse(x);access(y);splay(y);
		return tree[y].sum;
	}
}LCT;
void add(int x,int y){to[++e]=y;ne[e]=be[x];be[x]=e;}
void dfs(int x,int fa){
	for(int i=be[x];i;i=ne[i]){
		int v=to[i];
		if(v!=fa){
			tree[v].fa=x;
			dfs(v,x);
		}
	}
}
int main(){
	int n=read(),m=read();
	for(int i=1;i<=n;i++){LCT.make_color(i,read()+1);tree[i].mark=0;}
	for(int i=1;i<n;i++){int x=read(),y=read();add(x,y);add(y,x);}
	dfs(1,0);
	char tp[10];
	while(m--){
		scanf("%s",tp);
		if(tp[0]=='Q'){int x=read(),y=read();printf("%d\n",LCT.query(x,y));}
		else{int x=read(),y=read(),w=read();LCT.update(x,y,w+1);}
	}
	return 0;
}


發佈了83 篇原創文章 · 獲贊 27 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章