2243: [SDOI2011]染色

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 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,表示xy之间有一条无向边。

下面 行每行描述一个操作:

“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<=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\n",find(a,b));
        }
    }
    return 0;
}

 

posted @ 2017-02-03 15:57  神犇(shenben)  阅读(209)  评论(0编辑  收藏  举报