【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;

}

你可能感兴趣的:(paint)