Description:
Hint:
(n le 10^5)
Solution:
掌握了线段树区间合并的套路,这题就很简单了,树剖之后用线段树维护左右颜色,和区间颜色段数,查询跳链时分类讨论一下中间的颜色是否相同,修改直接修改就行了,代码稍有细节
#include<bits/stdc++.h>
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int mxn=1e6+5;
int n,m,tot,cnt;
int a[mxn],v[mxn<<2],f[mxn],hd[mxn],lc[mxn],rc[mxn],sz[mxn],rk[mxn];
int dfn[mxn],top[mxn],son[mxn],coll[2],colr[2],dep[mxn],tag[mxn<<2];
struct ed {
int to,nxt;
}t[mxn<<1];
inline void add(int u,int v) {
t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
};
void push_up(int p)
{
lc[p]=lc[ls]; rc[p]=rc[rs]; v[p]=v[ls]+v[rs];
if(rc[ls]==lc[rs]) --v[p];
}
void push_down(int p)
{
if(tag[p]) {
tag[ls]=tag[rs]=tag[p];
v[ls]=v[rs]=1;
lc[ls]=lc[rs]=rc[ls]=rc[rs]=tag[p];
tag[p]=0;
}
}
void build(int l,int r,int p)
{
if(l==r) {
v[p]=1; lc[p]=rc[p]=a[rk[l]];
return ;
}
int mid=(l+r)>>1;
build(l,mid,ls);
build(mid+1,r,rs);
push_up(p);
}
void dfs1(int u,int fa)
{
f[u]=fa; sz[u]=1; dep[u]=dep[fa]+1;
for(int i=hd[u];i;i=t[i].nxt) {
int v=t[i].to;
if(v==fa) continue ;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp; dfn[u]=++tot; rk[tot]=u;
if(son[u]) dfs2(son[u],tp);
for(int i=hd[u];i;i=t[i].nxt) {
int v=t[i].to;
if(v==f[u]||v==son[u]) continue ;
dfs2(v,v);
}
}
void getcol(int l,int r,int ql,int qr,int id,int p)
{
if(ql<=l&&r<=qr) {
if(ql==l) coll[id]=lc[p];
if(qr==r) colr[id]=rc[p];
return ;
}
int mid=(l+r)>>1; push_down(p);
if(qr>mid) getcol(mid+1,r,ql,qr,id,rs);
if(ql<=mid) getcol(l,mid,ql,qr,id,ls);
push_up(p);
}
int query(int l,int r,int ql,int qr,int id,int p)
{
if(ql<=l&&r<=qr) return v[p];
int mid=(l+r)>>1; int lt=0,rt=0,res=0; push_down(p);
if(ql<=mid) res+=query(l,mid,ql,qr,id,ls),lt=1;
if(qr>mid) res+=query(mid+1,r,ql,qr,id,rs),rt=1;
if(lt&&rt) res-=(rc[ls]==lc[rs]); return res;
}
void update(int l,int r,int ql,int qr,int val,int p)
{
if(ql<=l&&r<=qr) {
tag[p]=val;
v[p]=1; lc[p]=rc[p]=val;
return ;
}
int mid=(l+r)>>1; push_down(p);
if(ql<=mid) update(l,mid,ql,qr,val,ls);
if(qr>mid) update(mid+1,r,ql,qr,val,rs);
push_up(p);
}
void solve(int x,int y)
{
int ans=0,las1=-1,las2=-1; coll[0]=coll[1]=colr[0]=colr[1]=-1; //注意颜色可能为0,因为这里调了好久
int fx=top[x],fy=top[y];
while(fx!=fy) {
if(dep[fx]>=dep[fy]) {
ans+=query(1,n,dfn[fx],dfn[x],0,1);
getcol(1,n,dfn[fx],dfn[x],0,1);
if(las1==colr[0]) --ans;
x=f[fx],fx=top[x]; las1=coll[0];
}
else {
ans+=query(1,n,dfn[fy],dfn[y],1,1);
getcol(1,n,dfn[fy],dfn[y],1,1);
if(las2==colr[1]) --ans;
y=f[fy],fy=top[y]; las2=coll[1];
}
}
if(dfn[x]>dfn[y]) swap(x,y),swap(las1,las2);
getcol(1,n,dfn[x],dfn[y],1,1);
printf("%d
",ans+query(1,n,dfn[x],dfn[y],1,1)-(colr[1]==las2)-(coll[1]==las1));
}
void modify(int x,int y,int z)
{
int fx=top[x],fy=top[y];
while(fx!=fy) {
if(dep[fx]>=dep[fy]) {
update(1,n,dfn[fx],dfn[x],z,1);
x=f[fx],fx=top[x];
}
else {
update(1,n,dfn[fy],dfn[y],z,1);
y=f[fy],fy=top[y];
}
}
if(dfn[x]>dfn[y]) swap(x,y);
update(1,n,dfn[x],dfn[y],z,1);
}
int main()
{
scanf("%d%d",&n,&m); char opt[5]; int u,v,w;
for(int i=1;i<=n;++i) scanf("%d",a+i);
for(int i=1;i<n;++i) {
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
dfs1(1,0); dfs2(1,1); build(1,n,1);
for(int i=1;i<=m;++i) {
scanf("%s",opt);
if(opt[0]=='Q') {
scanf("%d%d",&u,&v);
solve(u,v);
}
else if (opt[0]=='C') {
scanf("%d%d%d",&u,&v,&w);
modify(u,v,w);
}
}
return 0;
}