zoukankan      html  css  js  c++  java
  • BZOJ 2243: [SDOI2011]染色(树链剖分)


    2243: [SDOI2011] 染色

      Time Limit: 20 Sec
      Memory Limit: 512 MB

    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 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
      

    Sample Output 1###

      3
      1
      2

    HINT###

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

    题目地址: BZOJ 2243: [SDOI2011]染色

    题解:

         
      此题的关键是线段树记录的信息是什么
      线段树上记三个量:
      该段颜色段数,左端点颜色,右端点颜色
      在合并的时候段点颜色要特别小心仔细
      写法技巧和细节也很重要
      其余树链剖分
    www.cnblogs.com/AGFghy/


    AC代码

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    int n,m,u,v,x,y,c,num,cnt;
    int point[N<<1],next[N<<1],head[N];
    int fa[N],dep[N],size[N],son[N],id[N],top[N];
    int a[N],fc[N];
    char pd[5];
    struct node
    {
        int lc,rc,v,lazy;
    }tree[N<<2]; 
    void add(int u,int v)
    {
        point[++num]=v;
        next[num]=head[u];
        head[u]=num;
    }
    void dfs1(int now,int pre)
    {
        fa[now]=pre;
        dep[now]=dep[pre]+1;
        size[now]=1;
        for (int i=head[now]; i; i=next[i])
        {
            int v=point[i];
            if (v==pre) continue;
            dfs1(v,now);
            size[now]+=size[v];
            if (size[v]>size[son[now]]) son[now]=v;
        }
    }
    void dfs2(int now,int topf)
    {
        top[now]=topf;
        id[now]=++cnt;
        a[cnt]=fc[now]+1;
        if (!son[now]) return;
        dfs2(son[now],topf);
        for (int i=head[now]; i; i=next[i])
        {
            int v=point[i];
            if (v==fa[now] || v==son[now]) continue;
            dfs2(v,v);
        }
    }
    void pushup(int p)
    {
        tree[p].lc=tree[p<<1].lc;
        tree[p].rc=tree[(p<<1)+1].rc;
        tree[p].v=tree[p<<1].v+tree[(p<<1)+1].v-(tree[p<<1].rc==tree[(p<<1)+1].lc);
    }
    void pushdown(int p)
    {
        if (tree[p].lazy)
        {
            tree[p<<1].lc=tree[p<<1].rc=tree[p<<1].lazy=tree[p].lazy; tree[p<<1].v=1;
            tree[(p<<1)+1].lc=tree[(p<<1)+1].rc=tree[(p<<1)+1].lazy=tree[p].lazy; tree[(p<<1)+1].v=1;
            tree[p].lazy=0;
        }
    }
    void build(int l,int r,int p)
    {
        if (l==r)
        {
            tree[p].lc=tree[p].rc=a[l];
            tree[p].v=1;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,p<<1);
        build(mid+1,r,(p<<1)+1);
        pushup(p);
    }
    void update(int l,int r,int p,int s,int t,int c)
    {
        if (l==s && r==t)
        {
            tree[p].lc=tree[p].rc=tree[p].lazy=c;
            tree[p].v=1;
            return;
        }
        pushdown(p);
        int mid=(l+r)>>1;
        if (t<=mid) update(l,mid,p<<1,s,t,c);
        else if (s>mid) update(mid+1,r,(p<<1)+1,s,t,c);
        else
        {
            update(l,mid,p<<1,s,mid,c);
            update(mid+1,r,(p<<1)+1,mid+1,t,c);
        }
        pushup(p);
    }
    node query(int l,int r,int p,int s,int t)
    {
        if (l==s && r==t) return tree[p];
        pushdown(p);
        int mid=(l+r)>>1;
        if (t<=mid) return query(l,mid,p<<1,s,t);
        else if (s>mid) return query(mid+1,r,(p<<1)+1,s,t);
        else
        {
            node res,s1,s2;
            s1=query(l,mid,p<<1,s,mid);   s2=query(mid+1,r,(p<<1)+1,mid+1,t);
            res.lc=s1.lc; res.rc=s2.rc;
            res.v=s1.v+s2.v-(s1.rc==s2.lc);
            return res;
        }
    }
    void cover(int x,int y,int c)
    {
        while (top[x]!=top[y])
        {
            if (dep[top[x]]<dep[top[y]]) swap(x,y);
            update(1,n,1,id[top[x]],id[x],c);
            x=fa[top[x]];
        }
        if (dep[x]>dep[y]) swap(x,y);
        update(1,n,1,id[x],id[y],c);
    }
    int seg(int x,int y)
    {
        int xc=-1,yc=-1,ans=0;
        node now;
        while (top[x]!=top[y])
        {
             
            if (dep[top[x]]<dep[top[y]]) swap(x,y),swap(xc,yc);
            now=query(1,n,1,id[top[x]],id[x]);
            ans+=now.v-(now.rc==xc);
            xc=now.lc; x=fa[top[x]];
        }
        if (dep[x]>dep[y]) swap(x,y),swap(xc,yc);
        now=query(1,n,1,id[x],id[y]);
        ans+=now.v-(now.lc==xc)-(now.rc==yc);
        return ans; 
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1; i<=n; i++)
            scanf("%d",&fc[i]);
        for (int i=1; i<n; i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v); add(v,u);
        }
        dfs1(1,0);
        dfs2(1,1);
        build(1,n,1);
        while (m--)
        {
            scanf("%s",pd);
            if (pd[0]=='C') 
            {
                scanf("%d%d%d",&x,&y,&c);
                c++;
                cover(x,y,c);
            }
            if (pd[0]=='Q')
            {
                scanf("%d%d",&x,&y);
                printf("%d
    ",seg(x,y));
            }
        }
    }
    
    
  • 相关阅读:
    linux系统权限管理拓展:特殊权限
    Linux系统对文件及目录的权限管理(chmod、chown)
    linux 用户、用户组及相关命令(useradd 、passwd、userdel 、groupadd 、groupdel、usermod 、gpasswd 、 id、su)
    Tiny4412学习杂记
    Android 使用技巧
    Tiny4412 LED 硬件服务
    Android M AudioPolicy 分析
    qt程序异常结束crashed
    source in sight 删除工程
    qt数据库sql语句使用c++中的变量
  • 原文地址:https://www.cnblogs.com/AGFghy/p/9362865.html
Copyright © 2011-2022 走看看