2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6904 Solved: 2562
[Submit][Status][Discuss]
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]之间。
Source
/* 维护: lcol(当前区间左端点的颜色) rcol(当前区间右端点的颜色) sum(当前区间颜色段数量) 合并: sum=lson.sum+rson.sum-1{lson.rcol==rson.lcol} sum=lson.sum+rson.sum{lson.rcol!=rson.lcol} */ #include<cstdio> #include<iostream> #define lc k<<1 #define rc k<<1|1 #define O3 __attribute__((optimize("O3"))) #define IN inline using namespace std; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } char in(){ for(char ch=getchar();;ch=getchar()) if(ch>='A'&&ch<='Z') return ch; } const int M=1e5+5,N=M<<2; struct sgt{int lcol,rcol,sum,tag;}tr[N]; struct edge{int v,next;}e[N]; int n,m,tot,cnt,head[M],pos[M],dfn[M],val[M],son[M],top[M],dep[M],fa[M],siz[M]; IN void add(int x,int y){ e[++tot].v=y;e[tot].next=head[x];head[x]=tot; e[++tot].v=x;e[tot].next=head[y];head[y]=tot; } O3 void dfs(int x,int f,int de){ fa[x]=f;dep[x]=de;siz[x]=1; for(int i=head[x];i;i=e[i].next){ if(e[i].v!=f){ dfs(e[i].v,x,de+1); siz[x]+=siz[e[i].v]; if(!son[x]||siz[son[x]]<siz[e[i].v]) son[x]=e[i].v; } } } O3 void getpos(int x,int t1){ top[x]=t1;pos[x]=++cnt;dfn[cnt]=x; if(!son[x]) return ; getpos(son[x],t1); for(int i=head[x];i;i=e[i].next){ if(son[x]!=e[i].v&&fa[x]!=e[i].v){ getpos(e[i].v,e[i].v); } } } //=====================================================预处理 IN void updata(int k){ tr[k].lcol=tr[lc].lcol; tr[k].rcol=tr[rc].rcol; tr[k].sum=tr[lc].sum+tr[rc].sum-(tr[lc].rcol==tr[rc].lcol); } IN void pushdown(int k){ if(!tr[k].tag) return ; tr[lc].lcol=tr[lc].rcol=tr[k].tag; tr[rc].lcol=tr[rc].rcol=tr[k].tag; tr[lc].tag=tr[rc].tag=tr[k].tag; tr[lc].sum=tr[rc].sum=1; tr[k].tag=0; } O3 void build(int k,int l,int r){ if(l==r){ tr[k].lcol=tr[k].rcol=val[dfn[l]]; tr[k].sum=1; return ; } int mid=l+r>>1; build(lc,l,mid); build(rc,mid+1,r); updata(k); } O3 void change(int k,int l,int r,int x,int y,int v){ if(l==x&&r==y){ tr[k].sum=1; tr[k].lcol=tr[k].rcol=tr[k].tag=v; return ; } int mid=l+r>>1; pushdown(k); if(y<=mid) change(lc,l,mid,x,y,v); else if(x>mid) change(rc,mid+1,r,x,y,v); else change(lc,l,mid,x,mid,v),change(rc,mid+1,r,mid+1,y,v); updata(k); } O3 int query(int k,int l,int r,int x,int y){ if(l==x&&r==y) return tr[k].sum; pushdown(k); int mid=l+r>>1; if(y<=mid) return query(lc,l,mid,x,y); else if(x>mid) return query(rc,mid+1,r,x,y); else{ int res=query(lc,l,mid,x,mid)+query(rc,mid+1,r,mid+1,y); if(tr[lc].rcol==tr[rc].lcol) res--; return res; } } O3 int ask_l(int k,int l,int r,int x){ if(l==r) return tr[k].lcol; pushdown(k); int mid=l+r>>1; if(x<=mid) return ask_l(lc,l,mid,x); else return ask_l(rc,mid+1,r,x); } //=====================================================线段树 IN void modify(int x,int y,int c){ for(;top[x]!=top[y];x=fa[top[x]]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); change(1,1,n,pos[top[x]],pos[x],c); } //if(x==y) return ;1W if(dep[x]>dep[y]) swap(x,y); change(1,1,n,pos[x],pos[y],c); } IN int find(int x,int y){ int nc,fc,ans=0; for(;top[x]!=top[y];x=fa[top[x]]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); ans+=query(1,1,n,pos[top[x]],pos[x]); nc=ask_l(1,1,n,pos[top[x]]); fc=ask_l(1,1,n,pos[fa[top[x]]]); if(nc==fc) ans--; } //if(x==y) return ans;2W if(dep[x]>dep[y]) swap(x,y); ans+=query(1,1,n,pos[x],pos[y]); if(!ans) ans++; return ans; } //=====================================================树链剖分 int main(){ n=read();m=read(); for(int i=1;i<=n;i++) val[i]=read(); for(int i=1,x,y;i<n;i++){ x=read();y=read(); add(x,y); } dfs(1,1,1); getpos(1,1); build(1,1,n); for(int i=1,a,b,c;i<=m;i++){ c=in(); if(c=='C'){ a=read();b=read();c=read(); modify(a,b,c); } else{ a=read();b=read(); printf("%d ",find(a,b)); } } return 0; }