• BZOJ 2243 SDOI2011 染色


    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 10135  Solved: 3868
    [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

    Sample Output

    3
    1
    2

    HINT

    数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

    Source

    一眼就看出是树剖+线段树
    线段树需要维护cl,cr分别表示最左端和最右端分别是什么
    合并就是T[rt].sum=T[rt<<1].sum+T[rt<<1|1].sum-(T[rt<<1].cr==T[rt<<1|1].cl)
    因为在树链上往上跳的时候dfs序在减小   所以在树链上跳的时候拿一个变量来记录上个区间最左端的是什么 并在线段树查询的时候求一下当前链区间的右端是什么
    如果左端==右端 那么这两个区间的连续相同区间个数就是ans1+ans2-1 否则的话就是ans1+ans2
    然后依次向上计算即可
    /**************************************************************
        Problem: 2243
        User: zhangenming
        Language: C++
        Result: Accepted
        Time:7164 ms
        Memory:139476 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    #define ll long long
    #define inf 1e9+10
    using namespace std;
    inline int read(){
        int x=0;int f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int MAXN=1e6+10;
    struct node{
        int y,next;
    }e[MAXN];
    int linkk[MAXN],len,n,m,dfn[MAXN],dfs_clock,son[MAXN],siz[MAXN],x,y,v,top[MAXN],f[MAXN][21],ansl,ansr,ans,dep[MAXN],val[MAXN],low[MAXN];
    inline void insert(int x,int y){
        e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;
    }
    inline void dfs1(int x,int fa){
        f[x][0]=fa;siz[x]=1;dep[x]=dep[fa]+1;
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].y!=fa){
                dfs1(e[i].y,x);siz[x]+=siz[e[i].y];
                if(!son[x]) son[x]=e[i].y;
                else if(siz[e[i].y]>siz[son[x]]) son[x]=e[i].y;
            }
        }
    }
    inline void dfs2(int x,int fa){
        dfn[x]=++dfs_clock;top[x]=fa;low[dfs_clock]=x;
        if(son[x]) dfs2(son[x],fa);
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].y!=fa&&!dfn[e[i].y]){
                dfs2(e[i].y,e[i].y);
            }
        }
    }
    inline void getanser(){
        for(int i=1;i<=20;i++){
            for(int j=1;j<=n;j++){
                f[j][i]=f[f[j][i-1]][i-1];
            }
        }
    }
    inline int lca(int x,int y){
        if(x==y) return x;
        if(dep[x]<dep[y]) swap(x,y);
        for(int i=20;i>=0;i--){
            if(dep[x]-(1<<i)>=dep[y]) x=f[x][i];
        }
        if(x==y) return x;
        for(int i=20;i>=0;i--){
            if(f[x][i]!=f[y][i]&&f[x][i]!=0){
                x=f[x][i];y=f[y][i];
            }
        }
        return f[x][0];
    }
    struct sig{
        int cl,cr,sum,tag;
    }T[MAXN];
    inline void update(int rt){
        T[rt].sum=T[rt<<1].sum+T[rt<<1|1].sum;
        if(T[rt<<1].cr==T[rt<<1|1].cl) T[rt].sum--;
        T[rt].cl=T[rt<<1].cl;T[rt].cr=T[rt<<1|1].cr;
    }
    inline void downit(int rt){
        if(T[rt].tag!=-1){
            T[rt<<1].tag=T[rt<<1|1].tag=T[rt].tag;
            T[rt<<1].sum=1;T[rt<<1].cl=T[rt<<1].cr=T[rt].tag;
            T[rt<<1|1].sum=1;T[rt<<1|1].cl=T[rt<<1|1].cr=T[rt].tag;
            T[rt].tag=-1;
        }
    }
    inline void build(int l,int r,int rt){
        if(l==r){
            T[rt].sum=1;T[rt].cl=T[rt].cr=val[low[l]];
            T[rt].tag=-1;return ;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        T[rt].tag=-1;update(rt);
    }
    inline void insert(int l,int r,int rt){
        if(l!=r) downit(rt);
        if(l>=x&&r<=y){
            T[rt].sum=1;T[rt].cl=T[rt].cr=T[rt].tag=v;
            return;
        }
        if(l>y||r<x) return;
        int mid=(l+r)>>1;
        insert(l,mid,rt<<1);
        insert(mid+1,r,rt<<1|1);
        update(rt);
    }
    inline void query(int l,int r,int rt){
        if(l!=r) downit(rt);
        if(l>=x&&r<=y){
            if(ansl==-1) ansl=T[rt].cl,ansr=T[rt].cr,ans+=T[rt].sum;
            else{
                ans+=T[rt].sum;
                if(T[rt].cl==ansr) ans--;
                ansr=T[rt].cr;
            }
            return;
        }
        if(l>y||r<x) return;
        int mid=(l+r)>>1;
        query(l,mid,rt<<1);
        query(mid+1,r,rt<<1|1);
    }
    inline void change(){
        int a=read();int b=read();v=read();
        int t=lca(a,b);
        while(top[a]!=top[t]){
            x=dfn[top[a]],y=dfn[a];
            insert(1,n,1);a=f[top[a]][0];
        }
        x=dfn[t];y=dfn[a];insert(1,n,1);
        while(top[b]!=top[t]){
            x=dfn[top[b]],y=dfn[b];
            insert(1,n,1);b=f[top[b]][0];
        }
        x=dfn[t];y=dfn[b];insert(1,n,1);
    }
    inline void getsum(){
        int a=read();int b=read();
        int t=lca(a,b);int sum=0;
        int l=-1;
        while(top[a]!=top[t]){
            x=dfn[top[a]];y=dfn[a];ansl=ansr=-1;ans=0;
            query(1,n,1);a=f[top[a]][0];
            if(l==-1){
                l=ansl;sum+=ans;
            }
            else{
                sum+=ans;
                if(l==ansr) sum--;
                l=ansl;
            }
        }
        ansl=ansr=-1;ans=0;
        x=dfn[t];y=dfn[a];query(1,n,1);
        if(l==-1){
            l=ansl;sum+=ans;
        }
        else{
            sum+=ans;
            if(l==ansr) sum--;
            l=ansl;
        }
        l=-1;
        while(top[b]!=top[t]){
            x=dfn[top[b]];y=dfn[b];ansl=ansr=-1;ans=0;
            query(1,n,1);b=f[top[b]][0];
            if(l==-1){
                l=ansl;sum+=ans;
            }
            else{
                sum+=ans;
                if(l==ansr) sum--;
                l=ansl;
            }
        }
        ansl=ansr=-1;ans=0;
        x=dfn[t];y=dfn[b];query(1,n,1);
        if(l==-1){
            l=ansl;sum+=ans;
        }
        else{
            sum+=ans;
            if(l==ansr) sum--;
            l=ansl;
        }
        sum--;printf("%d
    ",sum); 
    }
    int main(){
        //freopen("All.in","r",stdin);
        //freopen("All.out","w",stdout);
        n=read();m=read();
        for(int i=1;i<=n;i++){
            val[i]=read();
        }
        for(int i=1;i<n;i++){
            int x=read();int y=read();
            insert(x,y);insert(y,x);
        }
        dfs1(1,0);dfs2(1,1);
        getanser();char ch[5];
        build(1,n,1);
        for(int i=1;i<=m;i++){
            scanf("%s",ch);
            if(ch[0]=='Q'){
                getsum();
            }
            else change();
        }
        return 0;
    }
    
    

      

  • 相关阅读:
    ubuntu 读取群晖 nas 盘
    nginx 下载 apk、ipa 不改名zip 设置
    centos 更新时间
    go 交叉编译跨平台
    ffmpeg安装
    批量打开文件夹下所有的指定文件(批处理)
    端口流量统计
    关于 bind 和 dns
    关于使用 certbot 给网站增加 ssl
    Macos下制作可启动的u盘(转)
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/9352004.html
Copyright © 2020-2023  润新知