【SDOI 2011】Paint 染色

  http://www.zybbs.org/JudgeOnline/problem.php?id=2243

  题目大意:给你一棵树,节点有颜色,要求可以查询某路径中连续颜色段的数目和修改某一段路径的颜色。

  两次拉实之后查询和修改即可。

  

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#define NIL LCT
#define MM 200001
#define MN 100001
using namespace std;

queue<int> q;
int n,m,a,b,c,color[MN];
char s[10];
struct EDGE{
	int pnt;
	EDGE *pre;
	EDGE (){}
	EDGE(int _pnt,EDGE *_pre):pnt(_pnt),pre(_pre){}
}Edge[MM],*EP=Edge,*edge[MM];

inline void addedge(int a,int b){
	edge[a]=new(++EP)EDGE(b,edge[a]);
	edge[b]=new(++EP)EDGE(a,edge[b]);
}

struct LinkCutTree{
	struct NODE{
		int c,lc,rc,mark,cnt;
		bool root;
		NODE *left,*right,*father;
		NODE (){}
		NODE(int _c,NODE *_left,NODE *_right,NODE *_father):c(_c),lc(_c),rc(_c),left(_left),right(_right),father(_father){
			mark=0,cnt=1,root=true;
		}
	}LCT[MN],*NP,*node[MN];
	
	void init(){
		NP=NIL;
		NIL->c=NIL->lc=NIL->rc=NIL->mark=0;
		NIL->left=NIL->right=NIL->father=NIL;
		NIL->root=false;
	}
	
	void build(){
		q.push(1);
		node[1]=new(++NP)NODE(color[1],NIL,NIL,NIL);
		while(!q.empty()){
			int i=q.front();q.pop();
			for(EDGE *j=edge[i];j;j=j->pre)
				if(node[j->pnt]!=node[i]->father){
					node[j->pnt]=new(++NP)NODE(color[j->pnt],NIL,NIL,node[i]);
					q.push(j->pnt);
				}
		}
	}
	
	void renew(NODE *&t,int key){
		if(t!=NIL) t->c=t->lc=t->rc=t->mark=key,t->cnt=1;
	}
	
	void pushdown(NODE *&t){
		if(t->mark){
			renew(t->left,t->mark);
			renew(t->right,t->mark);
			t->mark=0;
		}
	}
	
	void update(NODE *&t){
		t->lc=t->rc=t->c;
		if(t->left!=NIL) t->lc=t->left->lc;
		if(t->right!=NIL) t->rc=t->right->rc;
		t->cnt=t->left->cnt+t->right->cnt+1;
		if(t->c==t->left->rc) t->cnt--;
		if(t->c==t->right->lc) t->cnt--;
	}
	
	void zig(NODE *&t){
		NODE *f=t->father,*r=t->right;
		pushdown(f);
		pushdown(t);
		t->father=f->father;
		if(f->root) t->root=true,f->root=false;
		else{
			if(f->father->left==f) f->father->left=t;
			else f->father->right=t;
		}
		t->right=f,f->father=t,f->left=r,r->father=f;
		update(f);
	}
	
	void zag(NODE *&t){
		NODE *f=t->father,*l=t->left;
		pushdown(f);
		pushdown(t);
		t->father=f->father;
		if(f->root) t->root=true,f->root=false;
		else{
			if(f->father->left==f) f->father->left=t;
			else f->father->right=t;
		}
		t->left=f,f->father=t,f->right=l,l->father=f;
		update(f);
	}
	
	void splay(NODE *&t){
		pushdown(t);
		while(!t->root){
			if(t->father->root){
				if(t->father->left==t) zig(t);
				else zag(t);
			}else{
				if(t->father->father->left==t->father){
					if(t->father->left==t) zig(t->father),zig(t);
					else zag(t),zig(t);
				}else{
					if(t->father->left==t) zig(t),zag(t);
					else zag(t->father),zag(t);
				}
			}
		}
		update(t);
	}
	
	void Expose(NODE *&t){
		NODE *p=t,*q=NIL;
		while(p!=NIL){
			splay(p);
			p->right->root=true;
			p->right=q;
			p->right->root=false;
			update(p);
			q=p;p=p->father;
		}
	}
	
	void Modify(int a,int b,int c){
		Expose(node[a]);
		NODE *p=node[b],*q=NIL;
		while(p!=NIL){
			splay(p);
			if(p->father==NIL){
				p->c=c;
				renew(p->right,c);
				renew(q,c);
			}
			p->right->root=true;
			p->right=q;
			p->right->root=false;
			update(p);
			q=p;p=p->father;
		}
	}
	
	void query(int a,int b){
		Expose(node[a]);
		NODE *p=node[b],*q=NIL;
		while(p!=NIL){
			splay(p);
			if(p->father==NIL){
				int ans=q->cnt+p->right->cnt+1;
				if(p->c==q->lc) ans--;
				if(p->c==p->right->lc) ans--;
				printf("%d\n",ans);
			}
			p->right->root=true;
			p->right=q;
			p->right->root=false;
			update(p);
			q=p;p=p->father;
		}
	}
}tree;

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&color[i]);
	for(int i=1;i<n;i++){
		scanf("%d%d",&a,&b);
		addedge(a,b);
	}
	tree.init();
	tree.build();
	while(m--){
		scanf("%s",s);
		if(s[0]=='Q'){
			scanf("%d%d",&a,&b);
			tree.query(a,b);
		}else{
			scanf("%d%d%d",&a,&b,&c);
			tree.Modify(a,b,c);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Delostik/p/2134544.html