zoukankan      html  css  js  c++  java
  • 2243: [SDOI2011]染色

    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

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

     

     

    题解: 这个题就是树链剖分+线段树的问题,主要是线段树的合并的问题。

     

    #include<stdio.h>
    #include<string.h>
    #include<vector>
    #include<map>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int N=2e6+4;
    int n,w,_max,_sum;
    int flag,Rmost,Lmost;
    int sumv[N],maxv[N];
    int rank[N],tid[N],top[N],dp[N],fa[N],a[N],siz[N],son[N];
    int tot;
    int head[N];
    int c;
    int L[N],R[N];
    int setv[N];
    int tim;
    struct node
    {
        int u,v,next;
    }edge[N];
    void inist()
    {
        memset(head,-1,sizeof(head));
        for(int i=1;i<N;i++) setv[i]=-1;
    }
    void addedge(int u,int v)
    {
        edge[tot].u=u; edge[tot].v=v;
        edge[tot].next=head[u]; head[u]=tot++;
    }
    void build(int o,int l,int r)
    {
        if(l==r)
        {
            sumv[o]=1;
            L[o]=a[rank[l]];  R[o]=a[rank[l]];
            return;
        }
        int mid=(r+l)/2;
        build(o*2,l,mid);
        build(o*2+1,mid+1,r);
        if(R[o*2]!=L[o*2+1])
        sumv[o]=sumv[o*2]+sumv[o*2+1];
        else sumv[o]=sumv[o*2]+sumv[o*2+1]-1;
        L[o]=L[o*2];
        R[o]=R[o*2+1];
    }
    void maintain(int o,int l,int r)
    {
        int lc=o*2,rc=o*2+1;
        if(R[lc]!=L[rc]) sumv[o]=sumv[lc]+sumv[rc];
        else sumv[o]=sumv[lc]+sumv[rc]-1;
        L[o]=L[o*2];
        R[o]=R[o*2+1];
    }
    void query(int o,int l,int r,int ql,int qr)
    {
        if(setv[o]!=-1)
        {
            if(flag==0) Lmost=setv[o],_sum+=1,Rmost=setv[o],flag=1;
            else
            {
                if(Rmost!=setv[o]) _sum=_sum+1;
                Rmost=setv[o];
            }
        }
        else if(ql<=l&&qr>=r)
        {
            if(flag==0)
            {
                Lmost=L[o];
                _sum+=sumv[o];
                Rmost=R[o];
                flag=1;
            }
            else
            {
                if(Rmost!=L[o]) _sum=_sum+sumv[o];
                else _sum+=sumv[o]-1;
                Rmost=R[o];
            }
        }
        else
        {
            int mid=(r+l)/2;
            if(ql<=mid) query(o*2,l,mid,ql,qr);
            if(qr>mid) query(o*2+1,mid+1,r,ql,qr);
        }
    }
    void Puttage(int o,int l,int r)
    {
        int lc=o*2,rc=o*2+1;
        if(setv[o]!=-1)
        {
            setv[rc]=setv[lc]=setv[o];
            sumv[lc]=1; L[lc]=setv[lc]; R[lc]=setv[lc];
            sumv[rc]=1; L[rc]=setv[rc]; R[rc]=setv[rc];
            setv[o]=-1;
        }
    }
    void change(int o,int l,int r,int ql,int qr)
    {
        if(ql>r||qr<l) return;
        if(ql<=l&&qr>=r)
        {
            setv[o]=c;
            sumv[o]=1; L[o]=c;  R[o]=c;
            return;
        }
        Puttage(o,l,r);
        int mid=(r+l)>>1;
        change(o*2,l,mid,ql,qr);
        change(o*2+1,mid+1,r,ql,qr);
        maintain(o,l,r);
    }
    void dfs1(int u,int father,int d)
    {
        dp[u]=d;
        fa[u]=father;
        siz[u]=1;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int y=edge[i].v;
            if(y!=father)
            {
                dfs1(y,u,d+1);
                siz[u]+=siz[y];
                if(son[u]==0||siz[y]>siz[son[u]])
                {
                    son[u]=y;
                }
            }
        }
    }
    void dfs2(int u,int tp)
    {
        top[u]=tp;
        tid[u]=++tim;
        rank[tid[u]]=u;
        if(son[u]==0) return;
        dfs2(son[u],tp);
     
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int y=edge[i].v;
            if(y!=son[u]&&y!=fa[u])
            {
                dfs2(y,y);
            }
        }
    }
    void ANS(int u,int v)
    {
        int L_now_1,R_now_1,L_now_2,R_now_2;
        int sum1=0,sum2=0;
        int flag1=0,flag2=0;
        int f1=top[u],f2=top[v];
        while(top[u]!=top[v])
        {
            if(dp[top[u]]>dp[top[v]])
            {
                if(flag1==0)
                {
                    flag=0;
                    _sum=0;
                    query(1,1,n,tid[top[u]],tid[u]);
                    sum1+=_sum;
                    L_now_1=Lmost;
                    flag1=1;
                    u=fa[top[u]];
                }
                else
                {
                    flag=0;
                    _sum=0;
                    query(1,1,n,tid[top[u]],tid[u]);
                    R_now_1=Rmost;
                    if(L_now_1==R_now_1)
                    {
                        sum1=_sum+sum1-1;
                    }
     
                    else sum1+=_sum;
                    L_now_1=Lmost;
                    u=fa[top[u]];
                }
            }
            else
            {
                if(flag2==0)
                {
                    flag=0;
                    _sum=0;
                    query(1,1,n,tid[top[v]],tid[v]);
                    sum2+=_sum;
                    L_now_2=Lmost;
                    flag2=1;
                    v=fa[top[v]];
                }
                else
                {
                    flag=0;
                    _sum=0;
                    query(1,1,n,tid[top[v]],tid[v]);
                    R_now_2=Rmost;
                    if(L_now_2==R_now_2)
                    {
                        sum2+=_sum-1;
                    }
     
                    else sum2+=_sum;
                     L_now_2=Lmost;
                    v=fa[top[v]];
                }
            }
        }
        int temp=0;
        flag=0;
        _sum=0;
        query(1,1,n,min(tid[u],tid[v]),max(tid[u],tid[v]));
        if(tid[u]>tid[v])
        {
            if(flag1&&L_now_1==Rmost)
            {
                temp++;
            }
            if(flag2&&L_now_2==Lmost) temp++;
        }
        else
        {
            if(flag1&&L_now_1==Lmost)
            {
                temp++;
            }
            if(flag2&&L_now_2==Rmost) temp++;
        }
        printf("%d
    ",sum1+sum2+_sum-temp);
    }
    void Chan(int u,int v)
    {
        while(top[u]!=top[v])
        {
            if(dp[top[u]]<dp[top[v]])
            {
                swap(u,v);
            }
            change(1,1,n,tid[top[u]],tid[u]);
            u=fa[top[u]];
        }
        if(tid[u]>tid[v]) swap(u,v);
        change(1,1,n,tid[u],tid[v]);
    }
    int main()
    {
        int q;
        cin>>n>>q;
        inist();
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            addedge(a,b);
            addedge(b,a);
        }
        dfs1(1,1,1);
        dfs2(1,1);
        build(1,1,n);
        scanf("%d",&q);
        while(q--)
        {
            int u,v;
            char str[10];
            scanf("%s",str);
            if(str[0]=='C')
            {
                int a,b;
                scanf("%d%d%d",&a,&b,&c);
                Chan(a,b);
            }
            else if(str[0]=='Q')
            {
                scanf("%d%d",&u,&v);
                ANS(u,v);
            }
        }
    }
    

     

      

     

  • 相关阅读:
    带权并查集
    Dungeon Master (luo 三维 BFS )
    迷宫问题 (最短路径保存输出)
    Aggressive cows (北京大学ACM-ICPC竞赛训练暑期课 )
    滑雪 (北京大学ACM-ICPC竞赛训练暑期课 )
    棋盘问题 (北京大学ACM-ICPC竞赛训练暑期课 )
    简单的整数划分问题 ( 北京大学ACM-ICPC竞赛训练暑期课 )
    马走日 (DFS)
    蓝桥杯 (计算路径)
    最长单词 (分割字符串)(蓝桥杯-算法提高)
  • 原文地址:https://www.cnblogs.com/Heilce/p/7246132.html
Copyright © 2011-2022 走看看