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); } } }