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
对于每个询问操作,输出一行答案。
题解: 这个题就是树链剖分+线段树的问题,主要是线段树的合并的问题。
#include<stdio.h>
#include<string.h>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=2e6+4;
int n,w,_max,_sum;
int flag,Rmost,Lmost;
int sumv[N],maxv[N];
int rank[N],tid[N],top[N],dp[N],fa[N],a[N],siz[N],son[N];
int tot;
int head[N];
int c;
int L[N],R[N];
int setv[N];
int tim;
struct node
{
int u,v,next;
}edge[N];
void inist()
{
memset(head,-1,sizeof(head));
for(int i=1;i<N;i++) setv[i]=-1;
}
void addedge(int u,int v)
{
edge[tot].u=u; edge[tot].v=v;
edge[tot].next=head[u]; head[u]=tot++;
}
void build(int o,int l,int r)
{
if(l==r)
{
sumv[o]=1;
L[o]=a[rank[l]]; R[o]=a[rank[l]];
return;
}
int mid=(r+l)/2;
build(o*2,l,mid);
build(o*2+1,mid+1,r);
if(R[o*2]!=L[o*2+1])
sumv[o]=sumv[o*2]+sumv[o*2+1];
else sumv[o]=sumv[o*2]+sumv[o*2+1]-1;
L[o]=L[o*2];
R[o]=R[o*2+1];
}
void maintain(int o,int l,int r)
{
int lc=o*2,rc=o*2+1;
if(R[lc]!=L[rc]) sumv[o]=sumv[lc]+sumv[rc];
else sumv[o]=sumv[lc]+sumv[rc]-1;
L[o]=L[o*2];
R[o]=R[o*2+1];
}
void query(int o,int l,int r,int ql,int qr)
{
if(setv[o]!=-1)
{
if(flag==0) Lmost=setv[o],_sum+=1,Rmost=setv[o],flag=1;
else
{
if(Rmost!=setv[o]) _sum=_sum+1;
Rmost=setv[o];
}
}
else if(ql<=l&&qr>=r)
{
if(flag==0)
{
Lmost=L[o];
_sum+=sumv[o];
Rmost=R[o];
flag=1;
}
else
{
if(Rmost!=L[o]) _sum=_sum+sumv[o];
else _sum+=sumv[o]-1;
Rmost=R[o];
}
}
else
{
int mid=(r+l)/2;
if(ql<=mid) query(o*2,l,mid,ql,qr);
if(qr>mid) query(o*2+1,mid+1,r,ql,qr);
}
}
void Puttage(int o,int l,int r)
{
int lc=o*2,rc=o*2+1;
if(setv[o]!=-1)
{
setv[rc]=setv[lc]=setv[o];
sumv[lc]=1; L[lc]=setv[lc]; R[lc]=setv[lc];
sumv[rc]=1; L[rc]=setv[rc]; R[rc]=setv[rc];
setv[o]=-1;
}
}
void change(int o,int l,int r,int ql,int qr)
{
if(ql>r||qr<l) return;
if(ql<=l&&qr>=r)
{
setv[o]=c;
sumv[o]=1; L[o]=c; R[o]=c;
return;
}
Puttage(o,l,r);
int mid=(r+l)>>1;
change(o*2,l,mid,ql,qr);
change(o*2+1,mid+1,r,ql,qr);
maintain(o,l,r);
}
void dfs1(int u,int father,int d)
{
dp[u]=d;
fa[u]=father;
siz[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int y=edge[i].v;
if(y!=father)
{
dfs1(y,u,d+1);
siz[u]+=siz[y];
if(son[u]==0||siz[y]>siz[son[u]])
{
son[u]=y;
}
}
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
tid[u]=++tim;
rank[tid[u]]=u;
if(son[u]==0) return;
dfs2(son[u],tp);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int y=edge[i].v;
if(y!=son[u]&&y!=fa[u])
{
dfs2(y,y);
}
}
}
void ANS(int u,int v)
{
int L_now_1,R_now_1,L_now_2,R_now_2;
int sum1=0,sum2=0;
int flag1=0,flag2=0;
int f1=top[u],f2=top[v];
while(top[u]!=top[v])
{
if(dp[top[u]]>dp[top[v]])
{
if(flag1==0)
{
flag=0;
_sum=0;
query(1,1,n,tid[top[u]],tid[u]);
sum1+=_sum;
L_now_1=Lmost;
flag1=1;
u=fa[top[u]];
}
else
{
flag=0;
_sum=0;
query(1,1,n,tid[top[u]],tid[u]);
R_now_1=Rmost;
if(L_now_1==R_now_1)
{
sum1=_sum+sum1-1;
}
else sum1+=_sum;
L_now_1=Lmost;
u=fa[top[u]];
}
}
else
{
if(flag2==0)
{
flag=0;
_sum=0;
query(1,1,n,tid[top[v]],tid[v]);
sum2+=_sum;
L_now_2=Lmost;
flag2=1;
v=fa[top[v]];
}
else
{
flag=0;
_sum=0;
query(1,1,n,tid[top[v]],tid[v]);
R_now_2=Rmost;
if(L_now_2==R_now_2)
{
sum2+=_sum-1;
}
else sum2+=_sum;
L_now_2=Lmost;
v=fa[top[v]];
}
}
}
int temp=0;
flag=0;
_sum=0;
query(1,1,n,min(tid[u],tid[v]),max(tid[u],tid[v]));
if(tid[u]>tid[v])
{
if(flag1&&L_now_1==Rmost)
{
temp++;
}
if(flag2&&L_now_2==Lmost) temp++;
}
else
{
if(flag1&&L_now_1==Lmost)
{
temp++;
}
if(flag2&&L_now_2==Rmost) temp++;
}
printf("%d
",sum1+sum2+_sum-temp);
}
void Chan(int u,int v)
{
while(top[u]!=top[v])
{
if(dp[top[u]]<dp[top[v]])
{
swap(u,v);
}
change(1,1,n,tid[top[u]],tid[u]);
u=fa[top[u]];
}
if(tid[u]>tid[v]) swap(u,v);
change(1,1,n,tid[u],tid[v]);
}
int main()
{
int q;
cin>>n>>q;
inist();
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
}
dfs1(1,1,1);
dfs2(1,1);
build(1,1,n);
scanf("%d",&q);
while(q--)
{
int u,v;
char str[10];
scanf("%s",str);
if(str[0]=='C')
{
int a,b;
scanf("%d%d%d",&a,&b,&c);
Chan(a,b);
}
else if(str[0]=='Q')
{
scanf("%d%d",&u,&v);
ANS(u,v);
}
}
}