#题目描述
给定一棵有n个节点的无根树和m个操作,操作有2类:
- 将节点a到节点b路径上所有点都染成颜色c;
- 询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
#做法
树链剖分x线段树模版题
#AC Code
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const int maxn=444444;
const int ls(const int &x){return x<<1;}
const int rs(const int &x){return x<<1|1;}
struct tree{
int l,r,c;
tree(int _l=-1,int _r=-1,int _c=0):l(_l),r(_r),c(_c){}
friend tree operator + (const tree &s,const tree &t)
{
return (s.l==-1)?(t):((t.l==-1)?(s):(tree(s.l,t.r,s.c+t.c-(s.r==t.l))));
}
}T[maxn];
//--
int color[maxn],pos[maxn],seg[maxn],lazy[maxn];
int top[maxn],h[maxn],dep[maxn],sz[maxn];
int n,m,id;
int q[maxn],fa[maxn],qf,qt;
vector <int> e[maxn];
vector <int>::iterator vi;
void set(int x,int v)
{
T[x]=tree(lazy[x]=v,v,1);
}
void push(int x)
{
if (~lazy[x])
{
set(ls(x),lazy[x]);
set(rs(x),lazy[x]);
lazy[x]=-1;
}
}
void build(int x,int l,int r)
{
lazy[x]=-1;
if (l==r)
{
T[x]=tree(seg[l],seg[l],1);
return;
}
int mid=(l+r)/2;
if (l<=mid)
build(ls(x),l,mid);
if (r>mid)
build(rs(x),mid+1,r);
T[x]=T[ls(x)]+T[rs(x)];
}
void paint(int x,int l,int r,int cl,int cr,int c)
{
if (cl<=l && cr>=r)
{
set(x,c);
return;
}
push(x);
int mid=(l+r)/2;
if (cl<=mid)
paint(ls(x),l,mid,cl,cr,c);
if (cr>mid)
paint(rs(x),mid+1,r,cl,cr,c);
T[x]=T[ls(x)]+T[rs(x)];
}
tree query(int x,int l,int r,int ql,int qr)
{
if (ql<=l && qr>=r)
return T[x];
tree tl,tr;
push(x);
int mid=(l+r)/2;
if (ql<=mid)
tl=query(ls(x),l,mid,ql,qr);
if (qr>mid)
tr=query(rs(x),mid+1,r,ql,qr);
return tl+tr;
}
void paint(int x,int y,int c)
{
while (top[x]!=top[y])
if (dep[top[x]]>dep[top[y]])
paint(1,1,n,pos[top[x]],pos[x],c),x=fa[top[x]];
else
paint(1,1,n,pos[top[y]],pos[y],c),y=fa[top[y]];
if (dep[x]>dep[y])
paint(1,1,n,pos[y],pos[x],c);
else
paint(1,1,n,pos[x],pos[y],c);
}
int query(int x,int y)
{
tree l,r;
while (top[x]!=top[y])
if (dep[top[x]]>dep[top[y]])
l=query(1,1,n,pos[top[x]],pos[x])+l,x=fa[top[x]];
else
r=query(1,1,n,pos[top[y]],pos[y])+r,y=fa[top[y]];
if (dep[x]>dep[y])
l=query(1,1,n,pos[y],pos[x])+l;
else
r=query(1,1,n,pos[x],pos[y])+r;
swap(l.l,l.r);
return (l+r).c;
}
int main()
{
char op[5];
int u,v,c;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&color[i]);
for (int i=1;i<n;i++)
scanf("%d%d",&u,&v),e[u].push_back(v),e[v].push_back(u);
q[qf=qt=1]=1;dep[1]=1;
for (;qf<=qt;qf++)
{
u=q[qf];
for (vi=e[u].begin();vi!=e[u].end();vi++)
{
if (!dep[*vi])
{
dep[*vi]=dep[u]+1;
fa[*vi]=u;
q[++qt]=*vi;
}
}
}
fa[1]=0;
for (int i=qt;i>=1;i--)
{
u=q[i];
sz[fa[u]]+=++sz[u];
if (sz[u]>sz[h[fa[u]]])
h[fa[u]]=u;
}
for (int i=1;i<=qt;i++)
{
u=q[i];
if (!top[u])
for(v=u;v;v=h[v])
{
top[v]=u;
pos[v]=++id;
seg[id]=color[v];
}
}
memset(lazy,-1,sizeof(lazy));
build(1,1,n);
for (int i=1;i<=m;i++)
{
scanf("%s",op);
if (op[0]=='C')
scanf("%d%d%d",&u,&v,&c),paint(u,v,c);
else
scanf("%d%d",&u,&v),printf("%d\n",query(u,v));
}
return 0;
}