rt似乎是错在树上查询?
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn=1e5+7;
const LL inf=5e18+7;
LL N,M;
struct SegmentTree{
struct Node{
Node* ls=NULL,* rs=NULL;
LL dat=1,Lcolor=0,Rcolor=0,setv=0;
void DelSons(){
if(ls)delete ls;
if(rs)delete rs;
ls=rs=NULL;
}
~Node(){DelSons();}
}root;
#define ls(p) p.ls
#define rs(p) p.rs
void pushup(Node& p){
p.Lcolor=ls(p)->Lcolor;p.Rcolor=rs(p)->Rcolor;
p.dat=ls(p)->dat+rs(p)->dat;
if(ls(p)->Rcolor==rs(p)->Lcolor)p.dat--;
if(p.dat==1)p.DelSons();
}
void pushdown(Node& p){
if(!ls(p))ls(p)=new Node();
if(!rs(p))rs(p)=new Node();
if(p.setv!=0){
ls(p)->Lcolor=ls(p)->Rcolor=rs(p)->Lcolor=rs(p)->Rcolor=ls(p)->setv=rs(p)->setv=p.setv;
ls(p)->dat=rs(p)->dat=1;
p.setv=0;
}
}
void ModifyPoint(Node& p,LL L,LL R,LL inx,LL xx){
if(L>=R){
p.setv=p.Lcolor=p.Rcolor=xx;p.dat=1;
return;
}
pushdown(p);LL mid=(L+R)>>1;
if(inx<=mid)ModifyPoint(*ls(p),L,mid,inx,xx);
else ModifyPoint(*rs(p),mid+1,R,inx,xx);
pushup(p);
}
void ModifyPoint(LL inx,LL xx){ModifyPoint(root,1,N,inx,xx);}
void ModifyRange(Node& p,LL L,LL R,LL ql,LL qr,LL xx){
if(ql<=L&&R<=qr){
p.setv=p.Lcolor=p.Rcolor=xx;p.dat=1;
p.DelSons();
return;
}
pushdown(p);LL mid=(L+R)>>1;
if(ql<=mid)ModifyRange(*ls(p),L,mid,ql,qr,xx);
if(mid+1<=qr)ModifyRange(*rs(p),mid+1,R,ql,qr,xx);
pushup(p);
}
void ModifyRange(LL ql,LL qr,LL xx){ModifyRange(root,1,N,ql,qr,xx);}
LL QueryRange(Node& p,LL L,LL R,LL ql,LL qr){
if(ql<=L&&R<=qr)return p.dat;
pushdown(p);LL mid=(L+R)>>1,ret=0;
if(ql<=mid)ret+=QueryRange(*ls(p),L,mid,ql,qr);
if(mid+1<=qr)ret+=QueryRange(*rs(p),mid+1,R,ql,qr);
if(ql<=mid&&mid+1<=qr&&ls(p)->Rcolor==rs(p)->Lcolor)ret--;
return ret;
}
LL QueryRange(LL ql,LL qr){return QueryRange(root,1,N,ql,qr);}
LL QueryPoint(Node& p,LL L,LL R,LL inx){
if(L>=R)return p.Lcolor;
pushdown(p);LL mid=(L+R)>>1;
if(inx<=mid)return QueryPoint(*ls(p),L,mid,inx);
else return QueryPoint(*rs(p),mid+1,R,inx);
}
LL QueryPoint(LL inx){return QueryPoint(root,1,N,inx);}
};
struct ZLPF{
LL head[maxn<<1],nxt[maxn<<1],to[maxn<<1],cnt_edge;
LL size[maxn],fa[maxn],dep[maxn],id[maxn],Hson[maxn],Hd[maxn],dfn;
LL val[maxn];
SegmentTree SEG;
void AddEdge(LL u,LL v){
nxt[++cnt_edge]=head[u];to[cnt_edge]=v;head[u]=cnt_edge;
nxt[++cnt_edge]=head[v];to[cnt_edge]=u;head[v]=cnt_edge;
}
void dfs1(LL u,LL v){
size[u]=1;fa[u]=v;dep[u]=dep[v]+1;
for(int i=head[u];i;i=nxt[i]){
if(to[i]==v)continue;
dfs1(to[i],u);size[u]+=size[to[i]];
if(size[to[i]]>size[Hson[u]])Hson[u]=to[i];
}
}
void dfs2(LL u,LL Top){
id[u]=++dfn;Hd[u]=Top;
if(!Hson[u])return;dfs2(Hson[u],Top);
for(int i=head[u];i;i=nxt[i]){
if(to[i]==fa[u]||to[i]==Hson[u])continue;
dfs2(to[i],to[i]);
}
}
void init(){
scanf("%lld%lld",&N,&M);
for(int i=1;i<=N;i++)scanf("%lld",&val[i]);
for(int i=1;i<N;i++){
LL u,v;scanf("%lld%lld",&u,&v);
AddEdge(u,v);
}
dfs1(1,0);dfs2(1,1);
for(int i=1;i<=N;i++)SEG.ModifyPoint(id[i],val[i]);
}
void ModifyRangeOnTree(LL u,LL v,LL xx){
while(Hd[u]!=Hd[v]){
if(dep[Hd[u]]<dep[Hd[v]])swap(u,v);
SEG.ModifyRange(id[Hd[u]],id[u],xx);
u=fa[Hd[u]];
}
if(dep[u]<dep[v])swap(u,v);
SEG.ModifyRange(id[v],id[u],xx);
}
LL QueryRangeOnTree(LL u,LL v){
LL ret=0,Ucolor=-1,Vcolor=-1;
while(Hd[u]!=Hd[v]){
if(dep[Hd[u]]<dep[Hd[v]]){
ret+=SEG.QueryRange(id[Hd[v]],id[v]);
LL NowColor=SEG.QueryPoint(id[v]);
if(NowColor==Vcolor)ret--;
Vcolor=SEG.QueryPoint(id[Hd[v]]);
v=fa[Hd[v]];
}else{
ret+=SEG.QueryRange(id[Hd[u]],id[u]);
LL NowColor=SEG.QueryPoint(id[u]);
if(NowColor==Ucolor)ret--;
Ucolor=SEG.QueryPoint(id[Hd[u]]);
u=fa[Hd[u]];
}
}
if(dep[u]<dep[v]){
ret+=SEG.QueryRange(id[u],id[v]);
LL NowColor=SEG.QueryPoint(id[v]);
if(NowColor==Ucolor||NowColor==Vcolor)ret--;
}else{
ret+=SEG.QueryRange(id[v],id[u]);
LL NowColor=SEG.QueryPoint(id[u]);
if(NowColor==Ucolor||NowColor==Vcolor)ret--;
}
return ret;
}
void Query(){
for(int i=1;i<=M;i++){
char op;
LL u,v,color;
cin>>op;
if(op=='C'){
cin>>u>>v>>color;
ModifyRangeOnTree(u,v,color);
}
else if(op=='Q'){
cin>>u>>v;
printf("%lld\n",QueryRangeOnTree(u,v));
}
}
}
}Tree;
int main(){
//freopen("P2846.in","r",stdin);
//freopen("P2846.ans","w",stdout);
Tree.init();Tree.Query();
return 0;
}