如题,求调。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
static char buf[1000000],*p1=buf,*p2=buf,obuf[1000000],*p3=obuf;
#define flush() fwrite(obuf,p3-obuf,1,stdout)
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
//#define putchar(x) (p3-obuf<1000000)?(*p3++=x):(flush(),p3=obuf,*p3++=x)
template<typename T> inline void read(T&);
template<typename T> inline void write(T);
template<typename... Args> inline void read(Args& ...);
template<typename... Args> inline void write(Args ...);
const int N=10005;
int n,m;
vector<int> G[N];
int col[N];
int dep[N],fa[N],siz[N],son[N],top[N],dfn[N],rnk[N],tot;
inline void dfs(int u){
siz[u]=1,son[u]=-1;
for(int v:G[u]){
if(dep[v]) continue;
fa[v]=u,dep[v]=dep[u]+1;
dfs(v);
siz[u]+=siz[v];
if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v;
}
}
inline void dfs(int u,int t){
top[u]=t,rnk[dfn[u]=++tot]=u;
if(son[u]!=-1) dfs(son[u],t);
for(int v:G[u]) if(v!=fa[u]&&v!=son[u]) dfs(v,v);
}
class SegmentTree{
public:
struct node{
int sum,lc,rc,lazy;
node():sum(0),lc(0),rc(0),lazy(0){}
};
node work(node l,node r){
node ret=node();
ret.sum=l.sum+r.sum-(l.rc==r.lc);
ret.lc=l.lc,ret.rc=r.rc;
return ret;
}
private:
node tr[N<<2];
void push_down(const int& rt){
if(!tr[rt].lazy) return;
tr[rt<<1].sum=tr[rt<<1|1].sum=1;
tr[rt<<1].lc=tr[rt<<1].rc=tr[rt<<1|1].lc=tr[rt<<1|1].rc=tr[rt].lazy;
tr[rt<<1].lazy=tr[rt<<1|1].lazy;
tr[rt].lazy=0;
}
void build(const int& rt,const int& l,const int& r){
if(l==r){
tr[rt].sum=1,tr[rt].lc=tr[rt].rc=tr[rt].lazy=col[rnk[l]];
return;
}
const int mid=(l+r)>>1;
build(rt<<1,l,mid),build(rt<<1|1,mid+1,r);
tr[rt]=work(tr[rt<<1],tr[rt<<1|1]);
}
void updata(const int& rt,const int& l,const int& r,const int& L,const int& R,const int& val){
if(L<=l&&r<=R){
tr[rt].sum=1,tr[rt].lc=tr[rt].rc=tr[rt].lazy=val;
return;
}
push_down(rt);
const int mid=(l+r)>>1;
if(L<=mid) updata(rt<<1,l,mid,L,R,val);
if(R>mid) updata(rt<<1|1,mid+1,r,L,R,val);
tr[rt]=work(tr[rt<<1],tr[rt<<1|1]);
}
node query(const int& rt,const int& l,const int& r,const int& L,const int& R){
if(L<=l&&r<=R) return tr[rt];
push_down(rt);
const int mid=(l+r)>>1;
if(L<=mid&&R>mid) return work(query(rt<<1,l,mid,L,R),query(rt<<1|1,mid+1,r,L,R));
return L<=mid?query(rt<<1,l,mid,L,R):query(rt<<1|1,mid+1,r,L,R);
}
public:
SegmentTree(){}
void build(){build(1,1,n);}
void updata(int L,int R,int val){updata(1,1,n,L,R,val);}
node query(int L,int R){return query(1,1,n,L,R);}
};
SegmentTree tr;
void updata(int u,int v,int col){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
tr.updata(dfn[top[u]],dfn[u],col);
u=fa[top[u]];
}
if(dfn[u]>dfn[v]) swap(u,v);
tr.updata(dfn[u],dfn[v],col);
}
int query(int u,int v){
int ret=0,ul=0,vl=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v),swap(ul,vl);
SegmentTree::node now=tr.query(dfn[top[u]],dfn[u]);
ret+=now.sum-(now.rc==ul),ul=now.lc,u=fa[top[u]];
}
if(dfn[u]>dfn[v]) swap(u,v);
SegmentTree::node now=tr.query(dfn[u],dfn[v]);
return ret+now.sum-(now.lc==ul)-(now.rc==vl);
}
inline void solve(char opt=getchar(),int u=0,int v=0,int w=0){
while(opt==' '||opt=='\n') opt=getchar();
switch(opt){
case 'C':
read(u,v,w);
updata(u,v,w);
break;
case 'Q':
read(u,v);
write(query(u,v),'\n');
break;
}
}
signed main(){
// freopen("1.txt","r",stdin);
read(n,m);
for(int i=1;i<=n;i++) read(col[i]);
for(int i=1,u,v;i<n;i++){
read(u,v);
G[u].emplace_back(v),G[v].emplace_back(u);
}
dep[1]=1,dfs(1),dfs(1,1);
tr.build();
for(;m--;) solve();
flush();
return 0;
}
template<typename T> inline void read(T& x){
x=0;bool flag=0;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') flag=1;
if(flag) for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)-(ch&15);
else for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch&15);
}
template<typename T> inline void write(T x){
static int sta[40];
int top=0;
if(x<0){
putchar('-');
do sta[top++]=(-x)%10,x/=10;
while(x);
}
else{
do sta[top++]=x%10,x/=10;
while(x);
}
while(top) putchar(sta[--top]^48);
}
template<> inline void write(char x){putchar(x);}
template<typename... Args> inline void read(Args& ...args){(void)initializer_list<int>{(read(args),0)...};}
template<typename... Args> inline void write(Args ...args){(void)initializer_list<int>{(write(args),0)...};}