• 【bzoj】2243: [SDOI2011]染色(树链剖分)


    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 6514  Solved: 2371
    [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,表示xy之间有一条无向边。

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

    “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


    注意各种操作时候的边界操作即可,即如果两端接口处颜色相同,答案--。
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cstring>
      4 using namespace std;
      5 inline void read(int& x){
      6     char c=getchar();int p=1,n=0;
      7     while(c<'0'||c>'9'){if(c=='-')p=-1;c=getchar();}
      8     while(c>='0'&&c<='9'){n=n*10+c-'0';c=getchar();}
      9     x=p*n;
     10 }
     11 const int maxn=100000,maxm=maxn*2+10;
     12 #define root 1,n,1
     13 #define ls l,m,o<<1
     14 #define rs m+1,r,o<<1|1
     15 int n,m;
     16 int w[maxn];
     17 struct edge{
     18     int v,next;
     19 }a[maxm];
     20 int h[maxn],tot;
     21 void add_e(int x,int y){
     22     a[tot].v=y;
     23     a[tot].next=h[x];
     24     h[x]=tot++;
     25 }
     26 int sz[maxn],son[maxn],fa[maxn],dep[maxn];
     27 void dfs1(int u){
     28     sz[u]=1;son[u]=0;
     29     for(int i=h[u];~i;i=a[i].next){
     30         int v=a[i].v;
     31         if(v==fa[u])continue;
     32         fa[v]=u;
     33         dep[v]=dep[u]+1;
     34         dfs1(v);
     35         sz[u]+=sz[v];
     36         if(sz[v]>sz[son[u]])son[u]=v;
     37     }
     38 }
     39 int tid[maxn],top[maxn],rank[maxn],dfs_clock;
     40 void dfs2(int u,int anc){
     41     tid[u]=++dfs_clock;top[u]=anc;rank[tid[u]]=u;
     42     if(son[u]){
     43         dfs2(son[u],anc);
     44         for(int i=h[u];~i;i=a[i].next){
     45             int v=a[i].v;
     46             if(v==fa[u]||v==son[u])continue;
     47             dfs2(v,v);
     48         }
     49     }
     50 }
     51 int sum[maxn*4],tag[maxn*4],left[maxn*4],right[maxn*4];
     52 int ql,qr,val;
     53 inline void pushup(int o){
     54     left[o]=left[o<<1];right[o]=right[o<<1|1];
     55     sum[o]=sum[o<<1]+sum[o<<1|1];
     56     if(right[o<<1]==left[o<<1|1])sum[o]--;
     57 }
     58 inline void pushdown(int o,int m){
     59     if(tag[o]==-1||m==1)return;
     60     sum[o<<1]=sum[o<<1|1]=1;
     61     tag[o<<1]=tag[o<<1|1]=left[o<<1]=left[o<<1|1]=right[o<<1]=right[o<<1|1]=tag[o];
     62     tag[o]=-1;
     63 }
     64 void build(int l,int r,int o){
     65     tag[o]=-1;
     66     if(l==r){
     67         sum[o]=1;
     68         left[o]=right[o]=w[rank[l]];
     69         return;
     70     }
     71     int m=(l+r)>>1;
     72     build(ls);build(rs);
     73     pushup(o);
     74 }
     75 void update(int l,int r,int o){
     76     if(ql<=l&&r<=qr){
     77         tag[o]=left[o]=right[o]=val;
     78         sum[o]=1;
     79         return;
     80     }
     81     pushdown(o,r-l+1);
     82     int m=(l+r)>>1;
     83     if(ql<=m)update(ls);
     84     if(qr>m)update(rs);
     85     pushup(o);
     86 }
     87 void change(int x,int y){
     88     while(top[x]!=top[y]){
     89         if(dep[top[x]]<dep[top[y]])
     90             swap(x,y);
     91         ql=tid[top[x]];qr=tid[x];
     92         update(root);
     93         x=fa[top[x]];
     94     }
     95     if(dep[x]>dep[y])
     96         swap(x,y);
     97     ql=tid[x];qr=tid[y];
     98     update(root);
     99 }
    100 int query(int l,int r,int o){
    101     if(ql<=l&&r<=qr){
    102         return sum[o];
    103     }
    104     pushdown(o,r-l+1);
    105     int m=(l+r)/2,ret=0,flag1=0,flag2=0;
    106     if(ql<=m)ret+=query(ls),flag1=1;
    107     if(qr>m)ret+=query(rs),flag2=1;
    108     if(flag1==1&&flag2==1&&left[o<<1|1]==right[o<<1])ret--;
    109     return ret;
    110 }
    111 int getc(int l,int r,int o,int pos){
    112     if(l==r){
    113         return left[o];
    114     }
    115     pushdown(o,r-l+1);
    116     int m=(l+r)>>1;
    117     if(pos<=m)return getc(ls,pos);
    118     if(pos>m)return getc(rs,pos);
    119 }
    120 int ask(int x,int y){
    121     int ret=0;
    122     while(top[x]!=top[y]){
    123         if(dep[top[x]]<dep[top[y]])
    124             swap(x,y);
    125         ql=tid[top[x]];qr=tid[x];
    126         ret+=query(root);
    127         int ans1=getc(root,tid[top[x]]);
    128         int ans2=getc(root,tid[fa[top[x]]]);
    129         if(ans1==ans2)ret--;
    130         x=fa[top[x]];
    131     }
    132     if(dep[x]>dep[y])
    133         swap(x,y);
    134     ql=tid[x];qr=tid[y];
    135     ret+=query(root);
    136     return ret;
    137 }
    138 int main(){
    139 //    freopen("2243.in","r",stdin);
    140     read(n);read(m);
    141     for(int i=1;i<=n;i++)
    142         read(w[i]);
    143     memset(h,-1,sizeof h);tot=0;
    144     for(int i=1;i<=n-1;i++){
    145         int x,y;
    146         read(x);read(y);
    147         add_e(x,y);add_e(y,x);
    148     }
    149     dfs1(1);dfs_clock=0;dfs2(1,1);
    150     build(root);
    151     for(int i=1;i<=m;i++){
    152         char op[5];
    153         scanf("%s",&op);
    154         if(op[0]=='C'){
    155             int x,y;
    156             read(x);read(y);read(val);
    157             change(x,y);
    158         }else{
    159             int x,y;read(x);read(y);
    160             printf("%d
    ",ask(x,y));
    161         }
    162     }
    163     return 0;
    164 }

    后记:写完这道题以后,感觉自己对树剖和线段树的理解又深了一点,明天就是NOIp了,希望不要辜负自己这些日子来的努力!!!加油!!

  • 相关阅读:
    location.href使用方法总结
    Ubuntu 12.04 安装JDK 8和Eclipse
    【一】仿微信飞机大战cocos2d-x3.0rc1
    QTP的基本功能介绍
    Spring+Ibatis集成开发实例
    Java NIO与IO的差别和比較
    嵌入式Linux常见问题
    递归和迭代之间的差
    大约sources.list和apt-get [转载]
    JVM学习笔记(一)------的基本结构
  • 原文地址:https://www.cnblogs.com/yohanlong/p/6078391.html
Copyright © 2020-2023  润新知