[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\)个节点的初始颜色.

下面\(n-1\)行每行包含两个整数\(x\)\(y\),表示\(x\)\(y\)之间有一条无向边.

下面\(m\)行每行描述一个操作:

\(”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

Sample Output

3 
1 
2

HINT

\(N,M\;\leq\;10^5,c\;\in\;z,c\;\in\;[0, 10^9]\).

Solution

树链剖分+线段树.

每次上移的时候判断相邻两段端点是否同色即可.

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 100005
#define M 300005
using namespace std;
struct linetree{
    int l,r,lc,rc,cnt;
}lt[M];
struct graph{
    int nxt,to;
}e[M];
char c[2];
int g[N],a[N],w[N],n,m,u,v,k,l,cnt;
int f[N],p[N],dep[N],siz[N],son[N],top[N];
inline void addedge(int x,int y){
    e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
}
inline void dfs1(int u){
    int m=0;siz[u]=1;
    for(int i=g[u];i;i=e[i].nxt)
        if(!dep[e[i].to]){
            f[e[i].to]=u;
            dep[e[i].to]=dep[u]+1;
            dfs1(e[i].to);
            siz[u]+=siz[e[i].to];
            if(siz[e[i].to]>m){
                son[u]=e[i].to;
                m=siz[e[i].to];
            } 
        }
}
inline void dfs2(int u,int tp){
    top[u]=tp;p[u]=++cnt;w[cnt]=a[u];
    if(son[u]) dfs2(son[u],tp);
    for(int i=g[u];i;i=e[i].nxt)
        if(f[u]!=e[i].to&&e[i].to!=son[u])
            dfs2(e[i].to,e[i].to);
}
inline void build(int u,int l,int r){
    lt[u].l=l;lt[u].r=r;
    if(lt[u].l<lt[u].r){
        int lef=u<<1,rig=u<<1|1;
        int mid=(lt[u].l+lt[u].r)>>1;
        build(lef,l,mid);build(rig,mid+1,r);
        lt[u].cnt=lt[lef].cnt+lt[rig].cnt;
        if(lt[lef].rc==lt[rig].lc) --lt[u].cnt;
        lt[u].lc=lt[lef].lc;lt[u].rc=lt[rig].rc;
    }
    else{
        lt[u].cnt=1;lt[u].lc=lt[u].rc=w[lt[u].l];
    }
}
inline void cover(int u,int l,int r,int k){
    if(lt[u].l>=l&&lt[u].r<=r){
        lt[u].lc=lt[u].rc=k;lt[u].cnt=1;
    }
    else if(lt[u].l<lt[u].r){
        int lef=u<<1,rig=u<<1|1;
        int mid=(lt[u].l+lt[u].r)>>1;
        if(lt[u].cnt==1){
            lt[lef].cnt=lt[rig].cnt=1;
            lt[lef].lc=lt[lef].rc=lt[rig].lc=lt[rig].rc=lt[u].lc;
        }
        if(l<=mid) cover(lef,l,r,k);
        if(r>mid) cover(rig,l,r,k);
        lt[u].cnt=lt[lef].cnt+lt[rig].cnt;
        if(lt[lef].rc==lt[rig].lc) --lt[u].cnt;
        lt[u].lc=lt[lef].lc;lt[u].rc=lt[rig].rc;
    }
}
inline int ask(int u,int l,int r){
    if(lt[u].l>=l&&lt[u].r<=r)
        return lt[u].cnt;
    if(lt[u].l<lt[u].r){
        int lef=u<<1,rig=u<<1|1,ret=0;
        int mid=(lt[u].l+lt[u].r)>>1;
        if(lt[u].cnt==1){
            lt[lef].cnt=lt[rig].cnt=1;
            lt[lef].lc=lt[rig].lc=lt[lef].rc=lt[rig].rc=lt[u].lc;
        }
        if(l<=mid) ret+=ask(lef,l,r);
        if(r>mid) ret+=ask(rig,l,r);
        if(l<=mid&&r>mid&&lt[lef].rc==lt[rig].lc) --ret;
        return ret;
    }
}
inline int col(int u,int x){
    if(lt[u].l==x) return lt[u].lc;
    if(lt[u].r==x) return lt[u].rc;
    if(lt[u].l<lt[u].r){
        int lef=u<<1,rig=u<<1|1;
        int mid=(lt[u].l+lt[u].r)>>1;
        if(lt[u].cnt==1){
            lt[lef].cnt=lt[rig].cnt=1;
            lt[lef].lc=lt[rig].lc=lt[lef].rc=lt[rig].rc=lt[u].lc;
        }
        if(x<=mid) return col(lef,x);
        return col(rig,x);
    }
}
inline void cov(int x,int y,int k){
    int t;
    while(top[x]!=top[y]){    
        if(dep[top[x]]<dep[top[y]]){
            t=x;x=y;y=t;
        }
        cover(1,p[top[x]],p[x],k);
        x=f[top[x]]; 
    }
    if(p[x]>p[y]){
        t=x;x=y;y=t;
    }
    cover(1,p[x],p[y],k);
}
inline int q(int x,int y){
    int ret=0,t;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]){
            t=x;x=y;y=t;
        }
        ret+=ask(1,p[top[x]],p[x]);
        if(col(1,p[top[x]])==col(1,p[f[top[x]]])) --ret;
        x=f[top[x]];
    }
    if(p[x]>p[y]){
        t=x;x=y;y=t;
    }
    ret+=ask(1,p[x],p[y]);
    return ret;
}
inline int lca(int x,int y){
    int t;
    while(top[x]!=top[y]){    
        if(dep[top[x]]<dep[top[y]]){
            t=x;x=y;y=t;
        }
        x=f[top[x]]; 
    }
    if(p[x]>p[y]){
        t=x;x=y;y=t;
    }
    return x;
}
inline void Aireen(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    for(int i=1,x,y;i<n;++i){
        scanf("%d%d",&x,&y);
        addedge(x,y);addedge(y,x);
    }
    dep[1]=1;dfs1(1);
    cnt=0;dfs2(1,1);
    build(1,1,n);
    while(m--){
        scanf("%s%d%d",c,&u,&v);
        if(c[0]=='C'){
            scanf("%d",&k);cov(u,v,k); 
        }
        else{
            l=lca(u,v);
            printf("%d\n",q(u,v));
        }
    }
}
int main(){
    freopen("color.in","r",stdin);
    freopen("color.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}
posted @ 2016-12-25 13:32  Aireen_Ye  阅读(135)  评论(0编辑  收藏  举报
底部 顶部 留言板 归档 标签
Der Erfolg kommt nicht zu dir, du musst auf den Erfolg zugehen.