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
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
1
2
HINT
數N<=10^5,操作數M<=10^5,所有的顏色C爲整數且在[0, 10^9]之間。
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
#define lson th<<1
#define rson th<<1|1
typedef long long ll;
typedef long double ldb;
#define inf 999999999
#define pi acos(-1.0)
#define maxn 100010
struct edge{
int to,next;
}e[2*maxn];
int pos,tot,Lc,Rc;
int top[maxn],son[maxn],fa[maxn],dep[maxn],num[maxn],p[maxn],a[maxn],c[maxn],first[maxn];
void dfs1(int u,int pre,int deep)
{
int i,j,v;
dep[u]=deep;
fa[u]=pre;
num[u]=1;
for(i=first[u];i!=-1;i=e[i].next){
v=e[i].to;
if(v==pre)continue;
dfs1(v,u,deep+1);
num[u]+=num[v];
if(son[u]==-1 || num[son[u] ]<num[v])son[u]=v;
}
}
void dfs2(int u,int tp)
{
int i,j,v;
top[u]=tp;
if(son[u]!=-1){
p[u]=++pos;c[pos]=a[u];dfs2(son[u],tp);
}
else{
p[u]=++pos;c[pos]=a[u];return;
}
for(i=first[u];i!=-1;i=e[i].next){
v=e[i].to;
if(v==son[u] || v==fa[u])continue;
dfs2(v,v);
}
}
struct node{
int l,r,num,cl,cr,flag;
}b[4*maxn];
void pushup(int th)
{
b[th].cl=b[lson].cl;
b[th].cr=b[rson].cr;
b[th].num=b[lson].num+b[rson].num;
if(b[lson].cr==b[rson].cl)b[th].num--;
}
void pushdown(int th)
{
if(b[th].flag==1){
b[lson].flag=b[rson].flag=1;
b[lson].cl=b[lson].cr=b[rson].cl=b[rson].cr=b[th].cl;
b[lson].num=b[rson].num=1;
b[th].flag=-1;
}
}
void build(int l,int r,int th)
{
int mid;
b[th].l=l;b[th].r=r;
b[th].flag=-1;
if(l==r){b[th].cl=b[th].cr=c[l];b[th].num=1;return;}
mid=(b[th].l+b[th].r)/2;
build(l,mid,lson);build(mid+1,r,rson);
pushup(th);
}
void update(int l,int r,int color,int th)
{
int mid;
if(b[th].l==l && b[th].r==r){
b[th].num=1;b[th].flag=1;b[th].cl=b[th].cr=color;return;
}
pushdown(th);
mid=(b[th].l+b[th].r)/2;
if(r<=mid)update(l,r,color,lson);
else if(l>mid)update(l,r,color,rson);
else{update(l,mid,color,lson);update(mid+1,r,color,rson);}
pushup(th);
}
int question(int l,int r,int th,int L,int R)
{
int mid,num;
if(b[th].l==L)Lc=b[th].cl;
if(b[th].r==R)Rc=b[th].cr;
if(b[th].l==l && b[th].r==r){
return b[th].num;
}
pushdown(th);
mid=(b[th].l+b[th].r)/2;
if(r<=mid)return question(l,r,lson,L,R);
else if(l>mid)return question(l,r,rson,L,R);
else{
num=question(l,mid,lson,L,R)+question(mid+1,r,rson,L,R);
if(b[lson].cr==b[rson].cl)num--;
return num;
}
}
int solve(int u,int v)
{
int f1=top[u],f2=top[v];
int num=0,pre1,pre2;
pre1=pre2=-1;
while(f1!=f2){
if(dep[f1]<dep[f2]){swap(pre1,pre2);swap(f1,f2);swap(u,v);}
num+=question(p[f1],p[u],1,p[f1],p[u]);
if(pre1==Rc)num--;
pre1=Lc;u=fa[f1];f1=top[u];
}
if(dep[u]<dep[v]){swap(pre1,pre2);swap(u,v);}
num+=question(p[v],p[u],1,p[v],p[u]);
if(Rc==pre1)num--;
if(Lc==pre2)num--;
return num;
}
void gengxin(int u,int v,int value)
{
int f1=top[u],f2=top[v];
while(f1!=f2){
if(dep[f1]<dep[f2]){swap(f1,f2);swap(u,v);}
update(p[f1],p[u],value,1);
u=fa[f1];
f1=top[u];
}
if(dep[u]<dep[v])swap(u,v);
update(p[v],p[u],value,1);
}
void add(int u,int v)
{
tot++;
e[tot].next=first[u];e[tot].to=v;
first[u]=tot;
}
int main()
{
int i,j,n,m,u,v,f,g,h;
char s[10];
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(first,-1,sizeof(first));
memset(son,-1,sizeof(son));
pos=0;tot=0;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(i=1;i<=n-1;i++){
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs1(1,0,1);dfs2(1,1);build(1,pos,1);
for(i=1;i<=m;i++){
scanf("%s",s);
if(s[0]=='Q'){
scanf("%d%d",&f,&g);
printf("%d\n",solve(f,g));
}
else{
scanf("%d%d%d",&f,&g,&h);
gengxin(f,g,h);
}
}
}
return 0;
}