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