题目:
题解:
题解:
这个题要维护左右端点的颜色以及中间的颜色段数
然后能说的只有各个数组的意义了
num[i]真实树中的点i在线段树最底层的编号;tree[i]线段树底层编号为i的点在真树中的编号;woc[i]底层编号为i的点在整棵线段树中的编号
最后要注意的就是数据范围了,deep啥的都是N,线段树中是4N,连边的是2N
代码:#include <cstdio>
#include <iostream>
#define N 200000
#define MIN -1e9
using namespace std;
int nxt[N*2],point[N*2],v[N*2],tot=0,cnt=0,n;
int deep[N],size[N],fa[N],top[N],son[N],tree[N],num[N],totw=0;
int sum[N*4],ll[N*4],rr[N*4],delta[N*4],w[N],woc[N*4+5];
void addline(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void updata(int now)
{
sum[now]=sum[now<<1]+sum[now<<1|1];
if (rr[now<<1]==ll[now<<1|1]) sum[now]--;
ll[now]=ll[now<<1];
rr[now]=rr[now<<1|1];
}
void pushdown(int now)
{
if (delta[now])
{
delta[now<<1]=delta[now];
delta[now<<1|1]=delta[now];
sum[now<<1]=sum[now<<1|1]=1;
ll[now<<1]=rr[now<<1]=delta[now];
ll[now<<1|1]=rr[now<<1|1]=delta[now];
delta[now]=0;
}
}
void dfs_1(int now,int dep,int faa)
{
deep[now]=dep;
size[now]=1;
fa[now]=faa;
int maxx=MIN;
for (int i=point[now];i;i=nxt[i])
if (v[i]!=faa)
{
dfs_1(v[i],dep+1,now);
size[now]+=size[v[i]];
if (size[v[i]]>maxx)
{
maxx=size[v[i]];
son[now]=v[i];
}
}
}
void dfs_2(int now,int faa)
{
if (son[faa]!=now) top[now]=now;
else top[now]=top[faa];
num[now]=++totw;
if (son[now])
{
dfs_2(son[now],now);
for (int i=point[now];i;i=nxt[i])
if (v[i]!=son[now] && v[i]!=faa)
dfs_2(v[i],now);
}
}
void build(int now,int l,int r)
{
if (l==r)
{
woc[l]=now;
sum[now]=1;
ll[now]=rr[now]=w[tree[l]];
return;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
updata(now);
}
void change(int now,int l,int r,int lrange,int rrange,int v)
{
if (l>=lrange && r<=rrange)
{
sum[now]=1;
ll[now]=rr[now]=v;
delta[now]=v;
return;
}
pushdown(now);
int mid=(l+r)>>1;
if (mid>=lrange) change(now<<1,l,mid,lrange,rrange,v);
if (mid<rrange) change(now<<1|1,mid+1,r,lrange,rrange,v);
updata(now);
}
int qurry(int now,int l,int r,int lrange,int rrange)
{
if (l>=lrange && r<=rrange) return sum[now];
pushdown(now);
int mid=(l+r)>>1,ans=0;bool qd1,qd2;qd1=false; qd2=false;
if (mid>=lrange){ans+=qurry(now<<1,l,mid,lrange,rrange);qd1=true;}
if (mid<rrange){ans+=qurry(now<<1|1,mid+1,r,lrange,rrange);qd2=true;}
if (qd1 && qd2 && ll[now<<1|1]==rr[now<<1]) ans--;
updata(now);
return ans;
}
void work(int u,int v,int c,int id)
{
int f1=top[u],f2=top[v],summ=0;
while (f1!=f2)
{
if (deep[f1]<deep[f2])
{
swap(f1,f2); swap(u,v);
}
if (id==1) change(1,1,n,num[f1],num[u],c);
else{
summ+=qurry(1,1,n,num[f1],num[u]);
int zz=qurry(1,1,n,num[fa[f1]],num[fa[f1]]);
zz=qurry(1,1,n,num[f1],num[f1]);
if (ll[woc[num[f1]]]==ll[woc[num[fa[f1]]]]) summ--;
}
u=fa[f1]; f1=top[u];
}
if (num[u]>num[v]) swap(u,v);
if (id==1) change(1,1,n,num[u],num[v],c);
else{
summ+=qurry(1,1,n,num[u],num[v]);
printf("%d\n",summ);
}
}
int main()
{
int m,i,x,y,u,c,vv;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
scanf("%d",&w[i]);
for (i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
addline(x,y);
}
dfs_1(1,1,0);
dfs_2(1,0);
for (i=1;i<=n;i++) tree[num[i]]=i;
build(1,1,n);
for (i=1;i<=m;i++)
{
char st[5];
scanf("%s",st);
if (st[0]=='C')
{
scanf("%d%d%d",&u,&vv,&c);
work(u,vv,c,1);
}
else
{
scanf("%d%d",&u,&vv);
work(u,vv,0,2);
}
}
}