解析:增加三个变量lc(最左边的颜色),rc(最右边的颜色),sum(连续相同颜色区间段数)。然后就是区间合并的搞法。我就不详细解释了,估计你已经想到
如何做了。
代码
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=;
int N,M,C[maxn];
struct lct
{
lct *fa,*son[];
int rev,c,setc,lc,rc,sum;
};
struct LCT
{
lct data[maxn];
lct *null;
void init(int Size=maxn-) //初始化
{
null=data; //null指向首元素
for(int i=;i<=Size;i++)
{
data[i].son[]=data[i].son[]=data[i].fa=null;
data[i].rev=;
data[i].c=data[i].lc=data[i].rc=C[i];
data[i].setc=-;
data[i].sum=;
}
null->c=null->lc=null->rc=-;
null->sum=;
}
void push_rev(lct* x)
{
if(x==null) return;
x->rev=!x->rev;
swap(x->son[],x->son[]);
swap(x->lc,x->rc);
}
void push_setc(lct* x,int setc)
{
if(x==null) return;
x->c=setc;
x->setc=setc;
x->lc=setc;
x->rc=setc;
x->sum=;
}
void pushdown(lct* x)
{
if(x->setc!=-)
{
push_setc(x->son[],x->setc);
push_setc(x->son[],x->setc);
x->setc=-;
}
if(x->rev)
{
push_rev(x->son[]);
push_rev(x->son[]);
x->rev=;
}
}
void pushup(lct* x)
{
if(x==null) return;
x->sum=;
if(x->son[]!=null)
{
x->sum+=x->son[]->sum;
if(x->son[]->rc==x->c) x->sum--;
}
if(x->son[]!=null)
{
x->sum+=x->son[]->sum;
if(x->son[]->lc==x->c) x->sum--;
}
x->lc=x->c;
if(x->son[]!=null) x->lc=x->son[]->lc;
x->rc=x->c;
if(x->son[]!=null) x->rc=x->son[]->rc;
}
bool Same(lct* x,lct* &y) //判断x和x的父亲是否在同一树里
{
return (y=x->fa)!=null&&(y->son[]==x||y->son[]==x);
}
void Rotate(lct* x,int d) //翻转
{
lct* y=x->fa; //x的父亲
y->son[d^]=x->son[d];
if(x->son[d]!=null) x->son[d]->fa=y; //x的子节点的父亲指向y
x->fa=y->fa; //连接
if(y->fa->son[]==y) x->fa->son[]=x;
else if(y->fa->son[]==y) x->fa->son[]=x;
x->son[d]=y;
y->fa=x;
}
void Splay(lct* x)
{
pushdown(x); //清除标记
lct* y;
while(Same(x,y)) //没有到树的最顶点
{
pushdown(y);
pushdown(x);
Rotate(x,y->son[]==x); //翻转
pushup(y);
pushup(x);
}
}
lct* Access(lct* u) //打通路径,返回的是根
{
lct *v=null;
for(;u!=null;u=u->fa)
{
Splay(u);
u->son[]=v;
pushup(v=u);
}
return v;
}
lct* GetRoot(lct* x) //得到根
{
for(x=Access(x);pushdown(x),x->son[]!=null;x=x->son[]) pushup(x);
return x;
}
void MakeRoot(lct* x) //使x成为根
{
Access(x);
Splay(x);
push_rev(x);
}
void Link(lct* x,lct* y) //连接两个点
{
MakeRoot(x);
x->fa=y;
Access(x);
}
void Cut(lct* x,lct* y) //断开两个点
{
MakeRoot(x);
Access(y);
Splay(y);
y->son[]->fa=null;
y->son[]=null;
}
void SetC(lct* x,lct* y,int setc)
{
MakeRoot(x);
push_setc(Access(y),setc);
}
int Query(lct* x,lct* y)
{
MakeRoot(x);
Access(y);
Splay(y);
return y->sum;
}
}A;
int main()
{
scanf("%d%d",&N,&M);
for(int i=;i<=N;i++) scanf("%d",&C[i]);
A.init(N);
int x,y;
for(int i=;i<N;i++)
{
scanf("%d%d",&x,&y);
A.Link(A.data+x,A.data+y);
}
char op[];
int c;
while(M--)
{
scanf("%s%d%d",op,&x,&y);
if(op[]=='C') scanf("%d",&c);
if(op[]=='C') A.SetC(A.data+x,A.data+y,c);
else printf("%d\n",A.Query(A.data+x,A.data+y));
}
return ;
}