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