Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。
Sample Input
6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
Sample Output
3
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
Source
思维难度:省选
代码难度:省选
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=100005;
struct node{
int v,next;
}e[N*2];
struct tree{
int l,r,x,c,rx,lx;
}t[N*20];
int n,m,cnt,b[N],fa[N],deep[N],sz[N],top[N],son[N],a[N],h[N],tcnt,idx[N],pos[N];
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10;
x=x+c-'0';
c=getchar();
}
return x*f;
}
void add(int u,int v){
cnt++;
e[cnt].v=v;
e[cnt].next=h[u];
h[u]=cnt;
}
void dfs1(int u){
int mxx=0,hv=0;
sz[u]=1;
for(int i=h[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(deep[v]!=0)continue;
deep[v]=deep[u]+1;
fa[v]=u;
dfs1(v);
if(sz[v]>mxx){
mxx=sz[v];
hv=v;
}
sz[u]+=sz[v];
}
son[u]=hv;
}
void dfs2(int u){
idx[u]=++tcnt;
a[tcnt]=b[u];
if(son[u]==0)return;
top[son[u]]=top[u];
dfs2(son[u]);
for(int i=h[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(idx[v])continue;
top[v]=v;
dfs2(v);
}
}
inline int lson(int rt){
return rt*2;
}
inline int rson(int rt){
return rt*2+1;
}
inline void pushup(int rt){
t[rt].lx=t[lson(rt)].lx;t[rt].rx=t[rson(rt)].rx;
if(t[lson(rt)].rx!=t[rson(rt)].lx){
t[rt].x=t[lson(rt)].x+t[rson(rt)].x;
}
else{
t[rt].x=t[lson(rt)].x+t[rson(rt)].x-1;
}
}
void build(int l,int r,int rt){
t[rt].l=l;t[rt].r=r;t[rt].lx=a[l];t[rt].rx=a[r];
if(l==r){
pos[l]=rt;
t[rt].x=1;
return;
}
int mid=l+r>>1;
build(l,mid,lson(rt));
build(mid+1,r,rson(rt));
pushup(rt);
}
void pushdown(int rt){
if(t[rt].c==0)return;
if(t[rt].l==t[rt].r)return;
t[lson(rt)].x=t[rson(rt)].x=1;
t[lson(rt)].lx=t[lson(rt)].rx=t[rson(rt)].rx=t[rson(rt)].lx=t[rt].c;
t[lson(rt)].c=t[rson(rt)].c=t[rt].c;
t[rt].c=0;
}
void update(int l,int r,int val,int rt){
if(t[rt].l>=l&&t[rt].r<=r){
t[rt].x=1;
t[rt].lx=t[rt].rx=val;
t[rt].c=val;
return;
}
pushdown(rt);
int mid=t[rt].l+t[rt].r>>1;
if(l<=mid){
update(l,r,val,lson(rt));
}
if(r>mid){
update(l,r,val,rson(rt));
}
pushup(rt);
}
int query(int l,int r,int rt){
if(t[rt].l>=l&&t[rt].r<=r){
return t[rt].x;
}
pushdown(rt);
int mid=t[rt].l+t[rt].r>>1,ans=0;
if(l<=mid){
ans+=query(l,r,lson(rt));
}
if(r>mid){
if(ans){
if(t[lson(rt)].rx==t[rson(rt)].lx){
ans--;
}
}
ans+=query(l,r,rson(rt));
}
return ans;
}
void T_update(int x,int y,int val){
int tmp;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]){
tmp=x;x=y;y=tmp;
}
update(idx[top[x]],idx[x],val,1);
x=fa[top[x]];
}
if(idx[x]>idx[y]){
tmp=x;x=y;y=tmp;
}
update(idx[x],idx[y],val,1);
}
int T_query(int x,int y){
int tmp,ans=0;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]){
tmp=x;x=y;y=tmp;
}
ans+=query(idx[top[x]],idx[x],1);
query(idx[top[x]],idx[top[x]],1);
query(idx[fa[top[x]]],idx[fa[top[x]]],1);
if(t[pos[idx[top[x]]]].lx==t[pos[idx[fa[top[x]]]]].lx){
ans--;
}
x=fa[top[x]];
}
if(idx[x]>idx[y]){
tmp=x;x=y;y=tmp;
}
ans+=query(idx[x],idx[y],1);
return ans;
}
int main(){
int u,v,x,y,z;
char inc[5];
memset(h,-1,sizeof(h));
n=read();m=read();
for(int i=1;i<=n;i++){
b[i]=read();
}
for(int i=1;i<=n-1;i++){
u=read();v=read();
add(u,v);
add(v,u);
}
fa[1]=0;deep[1]=1;
dfs1(1);
top[1]=1;
dfs2(1);
build(1,n,1);
while(m--){
scanf("%s",inc);
if(inc[0]=='Q'){
x=read();y=read();
printf("%d\n",T_query(x,y));
}
else{
x=read();y=read();z=read();
T_update(x,y,z);
}
}
return 0;
}