洛谷 P2486 [SDOI2011]染色

题目描述

输入输出格式

输入格式:

 

 

输出格式:

 

对于每个询问操作,输出一行答案。

 

输入输出样例

输入样例#1:
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
输出样例#1:
3
1
2

说明

树链剖分。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
const int N=100001;
using namespace std;
vector<int>vec[N];
int n,m,num,tot,colure[N];
int deep[N],size[N],dad[N],top[N],id[N];
struct nond{
    int l,r,flag;
    int l_colure,r_colure,sum;
}tree[N*2];
int dfs(int x){
    size[x]=1;
    deep[x]=deep[dad[x]]+1;
    for(int i=0;i<vec[x].size();i++){
        if(vec[x][i]!=dad[x]){
            dad[vec[x][i]]=x;
            dfs(vec[x][i]);
            size[x]+=size[vec[x][i]];
        }
    }
}
int dfs1(int x){
    int t=0;num++;
    id[x]=num;//记录dfs序 
    if(!top[x])
        top[x]=x;
    for(int i=0;i<vec[x].size();i++)
        if(vec[x][i]!=dad[x]&&size[vec[x][i]]>size[t])
            t=vec[x][i];
    if(t){
        top[t]=top[x];
        dfs1(t);
    }
    for(int i=0;i<vec[x].size();i++)
        if(vec[x][i]!=dad[x]&&vec[x][i]!=t)
            dfs1(vec[x][i]);
}
void up(int now){
    int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2;//线段树,所以乘2,切记!!切记!! 
    tree[now].sum=tree[l].sum+tree[r].sum-(tree[r].l_colure==tree[l].r_colure);
    tree[now].l_colure=tree[l].l_colure;
    tree[now].r_colure=tree[r].r_colure;
} 
void build(int l,int r){
    tot++;
    tree[tot].l=l;
    tree[tot].r=r;
    int y=tot;
    if(tree[tot].l==tree[tot].r)
        return ;
    int mid=(tree[tot].l+tree[tot].r)/2;
    build(l,mid);
    build(mid+1,r);
    up(y);
}
void change(int now,int t,int x){
    if(tree[now].l==tree[now].r){
        tree[now].l_colure=tree[now].r_colure=tree[now].flag=x;
        tree[now].sum=1;
        return;
    }
    int mid=(tree[now].l+tree[now].r)/2;
    int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2;
    if(t<=mid)    change(l,t,x);
    else if(t>mid)    change(r,t,x);
    up(now);
}
void down(int now){
    if(tree[now].l==tree[now].r)
        return;
    int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2;
    tree[l].l_colure=tree[r].l_colure=tree[l].r_colure=tree[r].r_colure=tree[l].flag=tree[r].flag=tree[now].flag;
    tree[l].sum=tree[r].sum=1;
    tree[now].flag=0;
}
void change_many(int now,int pol,int por,int a){
    if(tree[now].l==pol&&tree[now].r==por){
        tree[now].flag=tree[now].l_colure=tree[now].r_colure=a;
        tree[now].sum=1;
        return;
    }
    if(tree[now].flag)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    int l=now+1,r=now+(tree[now+1].r-tree[now].l+1)*2;
    if(por<=mid)    change_many(l,pol,por,a);
    else if(pol>mid)    change_many(r,pol,por,a);
    else{
        change_many(l,pol,mid,a);
        change_many(r,mid+1,por,a);
    }
    up(now);
}
int change_ans(int u,int v,int a){
    while(top[u]!=top[v]){
        if(deep[top[u]]<deep[top[v]])    swap(u,v);
        change_many(1,id[top[u]],id[u],a);
        u=dad[top[u]];
    }
    if(id[u]>id[v])    swap(u,v);
    change_many(1,id[u],id[v],a);
}
int query(int now,int t){
    if(tree[now].l==tree[now].r)
        return tree[now].flag;
    if(tree[now].flag)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2;
    if(t<=mid)    query(l,t);
    else query(r,t);
}
int query_many(int now,int pol,int por){
    if(tree[now].l==pol&&tree[now].r==por){
        return tree[now].sum;
    }
    if(tree[now].flag)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    int l=now+1,r=now+(tree[now+1].r-tree[now+1].l+1)*2;
    if(por<=mid)    return query_many(l,pol,por);
    else if(pol>mid)    return query_many(r,pol,por);
    else{
        int t=query_many(l,pol,mid)+query_many(r,mid+1,por);
        if(tree[l].r_colure==tree[r].l_colure)    t--;
        return t;
    }
} 
void query_ans(int u,int v){
    int ans=0;
    while(top[u]!=top[v]){
        if(deep[top[u]]<deep[top[v]])    swap(u,v);
        ans+=query_many(1,id[top[u]],id[u]);
        if(query(1,id[dad[top[u]]])==query(1,id[top[u]]))    ans--;
        u=dad[top[u]];
    }
    if(id[u]>id[v])    swap(u,v);
    ans+=query_many(1,id[u],id[v]);
    cout<<ans<<endl;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&colure[i]);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        vec[x].push_back(y);
        vec[y].push_back(x);
    }
    dfs(1);
    dfs1(1);
    build(1,n);
    for(int i=1;i<=n;i++)
        change(1,id[i],colure[i]);
    char ch;int a,b,c;
    for(int i=1;i<=m;i++){
        cin>>ch;
        if(ch=='C'){
            scanf("%d%d%d",&a,&b,&c);
            change_ans(a,b,c);
        }
        else{
            scanf("%d%d",&a,&b);
            query_ans(a,b);
        }
    }
    return 0;
}

 

posted @ 2017-08-21 16:09  一蓑烟雨任生平  阅读(167)  评论(0编辑  收藏  举报