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

    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 8402  Solved: 3151
    [Submit][Status][Discuss]

    Description

    给定一棵有n个节点的无根树和m个操作,操作有2类:

    1、将节点a到节点b路径上所有点都染成颜色c

    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

    请你写一个程序依次完成这m个操作。

    Input

    第一行包含2个整数nm,分别表示节点数和操作数;

    第二行包含n个正整数表示n个节点的初始颜色

    下面行每行包含两个整数xy,表示xy之间有一条无向边。

    下面行每行描述一个操作:

    “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括ab)都染成颜色c

    “Q a b”表示这是一个询问操作,询问节点a到节点b(包括ab)路径上的颜色段数量。

    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]之间。

    思路{

      颜色段发现用树链剖分的时候记录一下区间左右端点,比较一下就可以了.

      有点码.....

    }

    #include<bits/stdc++.h>
    #define il inline
    #define RG register
    #define ll long long
    #define db double
    #define N 100010
    using namespace std;
    int w[N];
    struct ed{int nxt,to;}e[N*2];
    int head[N],tot,n,m;
    void LINK(int u,int v){e[tot].nxt=head[u];e[tot].to=v;head[u]=tot++;}
    void link(int u,int v){LINK(u,v),LINK(v,u);}
    namespace Tree{
    #define ls (o<<1)
    #define rs ((o<<1)|1)
    #define mid ((l+r)>>1)
      int id[N],top[N],deep[N],idw[N],fa[N],sz[N],hson[N],idn;
      int Sum[N*4],lc[N*4],rc[N*4],lazy[N*4];
      void dfs1(int u,int faa){
        deep[u]=deep[faa]+1;fa[u]=faa;sz[u]=1;
        for(int i=head[u];i!=-1;i=e[i].nxt)if(e[i].to!=faa){
        int v=e[i].to;dfs1(v,u);
        sz[u]+=sz[v];if(sz[v]>sz[hson[u]])hson[u]=v;
          }
      }
      void dfs2(int u,int toop){
        id[u]=++idn;idw[idn]=w[u];top[u]=toop;
        if(hson[u])dfs2(hson[u],toop);
        for(int i=head[u];i!=-1;i=e[i].nxt)
          if(e[i].to!=hson[u]&&e[i].to!=fa[u])
        dfs2(e[i].to,e[i].to);
      }
      void up(int o){
        Sum[o]=Sum[ls]+Sum[rs];
        if(rc[ls]==lc[rs])Sum[o]--;
        rc[o]=rc[rs],lc[o]=lc[ls];
      }
      void build(int o,int l,int r){
        if(l==r){Sum[o]=1,rc[o]=lc[o]=idw[l];return;}
        build(rs,mid+1,r),build(ls,l,mid);
        up(o);
      }
      void down(int o){
        if(lazy[o]){
          Sum[rs]=Sum[ls]=1;
          rc[rs]=lc[rs]=lazy[rs]=lazy[o];
          rc[ls]=lc[ls]=lazy[ls]=lazy[o];
          lazy[o]=0;
        }
      }
      void Modify(int o,int l,int r,int L,int R,int c){
        if(l!=r)down(o);
        if(l>=L&&r<=R){
          Sum[o]=1;
          rc[o]=lc[o]=lazy[o]=c;
          return;
        }
        if(mid<L)Modify(rs,mid+1,r,L,R,c);
        else if(mid>=R)Modify(ls,l,mid,L,R,c);
        else Modify(rs,mid+1,r,mid,R,c),Modify(ls,l,mid,L,mid,c);
        up(o);
      }
      int Query(int o,int l,int r,int L,int R){
        if(l!=r)down(o);
        if(l>=L&&r<=R)return Sum[o];
        if(mid<L)return Query(rs,mid+1,r,L,R);
        if(mid>=R)return Query(ls,l,mid,L,R);
        else return Query(rs,mid+1,r,L,R)+Query(ls,l,mid,L,R)-(rc[ls]==lc[rs]);
      }
      int Querycol(int o,int l,int r,int pos){
        if(l!=r)down(o);if(l==r)return rc[o];
        if(mid<pos)return Querycol(rs,mid+1,r,pos);
        else return Querycol(ls,l,mid,pos);
      }
      void work1(int x,int y,int c){
        while(top[x]!=top[y]){
          if(deep[top[x]]<deep[top[y]])swap(x,y);
          Modify(1,1,n,id[top[x]],id[x],c);
          x=fa[top[x]];
        }
        if(deep[x]>deep[y])swap(x,y);
        Modify(1,1,n,id[x],id[y],c);
      }
      void work2(int x,int y){
        ll sum(0);
        while(top[x]!=top[y]){
          if(deep[top[x]]<deep[top[y]])swap(x,y);
          sum+=Query(1,1,n,id[top[x]],id[x]);
          if(Querycol(1,1,n,id[top[x]])==Querycol(1,1,n,id[fa[top[x]]]))sum--;
          x=fa[top[x]];
        }
        if(deep[x]>deep[y])swap(x,y);
        sum+=Query(1,1,n,id[x],id[y]);
        cout<<sum<<"
    ";
      }
    }
    char C[2];
    int main(){
      memset(head,-1,sizeof(head));
      scanf("%d%d",&n,&m);
      for(int i=1;i<=n;++i)scanf("%d",&w[i]);
      for(int i=1;i<n;++i){int u,v;scanf("%d%d",&u,&v),link(u,v);}
      Tree::dfs1(1,1),Tree::dfs2(1,1);Tree::build(1,1,n);
      for(int i=1;i<=m;++i){
        scanf("%s",C);
        if(C[0]=='C'){
          int a,b,c;scanf("%d%d%d",&a,&b,&c);
          Tree::work1(a,b,c);
        }
        else {
          int a,b;scanf("%d%d",&a,&b);
          Tree::work2(a,b);
        }
      }
      return 0;
    }
    
  • 相关阅读:
    nvm的安装与使用
    webpack中import动态设置webpackChunkName方法
    css在背景图下加渐变色
    js实现时间戳转换
    js实现随机数和随机数组
    js实现导航自动切换请求数据
    jq、js获取select中option上的value值以及文本值
    js、jq实现select 下拉选择更多
    软件测试
    php
  • 原文地址:https://www.cnblogs.com/zzmmm/p/7512980.html
Copyright © 2011-2022 走看看