• 洛谷 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;
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    php 获取当前目录和当前文件夹
    学习笔记12(选做)
    学习笔记11
    OpenEuler 中C与汇编的混合编程
    OpenEuler中C语言中的函数调用测试
    学习笔记10
    电子公文传输系统验收3开发环境
    电子公文传输系统验收2功能测试
    socket编程
    socket课堂
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7404967.html
Copyright © 2020-2023  润新知