BZOJ2243: [SDOI2011]染色
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
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
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
题解Here!
树上操作,首选 树链剖分/LCT。
这题就只有10w,所以树剖即可。
线段树维护:区间颜色数,区间左右颜色。
上传时:直接加,如果 左区间的右颜色==右区间的左颜色,颜色数-1。
标记下传:直接左右颜色修改,颜色数赋为1。
记得在跳树链时判断一下起始节点的颜色是否要合并。
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define LSON rt<<1 #define RSON rt<<1|1 #define DATA(x) b[x].data #define DATAL(x) b[x].left #define DATAR(x) b[x].right #define SIGN(x) b[x].c #define LSIDE(x) b[x].l #define RSIDE(x) b[x].r #define MAXN 100010 using namespace std; int n,m,c=1,d=1; int val[MAXN],head[MAXN],id[MAXN],top[MAXN],deep[MAXN],son[MAXN],fa[MAXN],size[MAXN]; struct node1{ int next,to; }a[MAXN<<1]; struct node2{ int data,left,right,c; int l,r; }b[MAXN<<2]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } void add(int u,int v){ a[c].to=v; a[c].next=head[u]; head[u]=c++; a[c].to=u; a[c].next=head[v]; head[v]=c++; } void dfs1(int rt){ son[rt]=0;size[rt]=1; for(int i=head[rt];i;i=a[i].next){ int will=a[i].to; if(!deep[will]){ deep[will]=deep[rt]+1; fa[will]=rt; dfs1(will); size[rt]+=size[will]; if(size[will]>size[son[rt]])son[rt]=will; } } } void dfs2(int rt,int f){ id[rt]=d++;top[rt]=f; if(son[rt])dfs2(son[rt],f); for(int i=head[rt];i;i=a[i].next){ int will=a[i].to; if(will!=son[rt]&&will!=fa[rt]) dfs2(will,will); } } void pushup(int rt){ DATAL(rt)=DATAL(LSON);DATAR(rt)=DATAR(RSON); DATA(rt)=DATA(LSON)+DATA(RSON); if(DATAR(LSON)==DATAL(RSON))DATA(rt)--; } void pushdown(int rt){ if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return; SIGN(LSON)=DATAL(LSON)=DATAR(LSON)=SIGN(rt); DATA(LSON)=1; SIGN(RSON)=DATAL(RSON)=DATAR(RSON)=SIGN(rt); DATA(RSON)=1; SIGN(rt)=0; } void buildtree(int l,int r,int rt){ int mid; LSIDE(rt)=l; RSIDE(rt)=r; if(l==r){ DATA(rt)=0; return; } mid=l+r>>1; buildtree(l,mid,LSON); buildtree(mid+1,r,RSON); pushup(rt); } void update(int l,int r,int c,int rt){ int mid; if(l<=LSIDE(rt)&&RSIDE(rt)<=r){ SIGN(rt)=DATAL(rt)=DATAR(rt)=c; DATA(rt)=1; return; } pushdown(rt); mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)update(l,r,c,LSON); if(mid<r)update(l,r,c,RSON); pushup(rt); } int query(int l,int r,int rt){ int mid,ans=0; if(l<=LSIDE(rt)&&RSIDE(rt)<=r) return DATA(rt); pushdown(rt); mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)ans+=query(l,r,LSON); if(mid<r)ans+=query(l,r,RSON); if(l<=mid&&mid<r&&DATAR(LSON)==DATAL(RSON))ans--; return ans; } int qcolour(int l,int r,int rt){ int mid; if(l<=LSIDE(rt)&&RSIDE(rt)<=r) return DATAL(rt); pushdown(rt); mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)return qcolour(l,r,LSON); else return qcolour(l,r,RSON); } void work1(int x,int y,int z){ while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); update(id[top[x]],id[x],z,1); x=fa[top[x]]; } if(deep[x]>deep[y])swap(x,y); update(id[x],id[y],z,1); return; } void work2(int x,int y){ int s=0,left,right; while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); s+=query(id[top[x]],id[x],1); left=qcolour(id[top[x]],id[top[x]],1); right=qcolour(id[fa[top[x]]],id[fa[top[x]]],1); x=fa[top[x]]; if(left==right)s--; } if(deep[x]>deep[y])swap(x,y); s+=query(id[x],id[y],1); printf("%d\n",s==0?1:s); return; } void work(){ char ch[2]; int x,y,z; while(m--){ scanf("%s",ch);x=read();y=read(); if(ch[0]=='C'){ z=read(); work1(x,y,z); } if(ch[0]=='Q')work2(x,y); } } void init(){ int u,v; n=read();m=read(); for(int i=1;i<=n;i++)val[i]=read(); for(int i=1;i<n;i++){ u=read();v=read(); add(u,v); } deep[1]=fa[1]=1; dfs1(1); dfs2(1,1); buildtree(1,n,1); for(int i=1;i<=n;i++)update(id[i],id[i],val[i],1); } int main(){ init(); work(); return 0; }