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

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243

    树链剖分的点剖分+线段树。漏了一个小地方,调了一下午...... 还是要细心啊!

    结构体里lc表示这个区间的最左端的颜色,rc表示这个区间的最右端的颜色,sum表示这个区间的颜色段数目。回溯合并的时候要注意,左孩子的右端颜色要是等于右孩子左端颜色 sum就要-1。

    代码如下:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 using namespace std;
      5 const int MAXN = 2e5 + 5;
      6 struct data {
      7     int next , to;
      8 }edge[MAXN << 1];
      9 struct segtree {
     10     int l , r , sum , lazy; //sum表示颜色段数量,lazy表示颜色延迟标记
     11     int lc , rc; //lc表示区间的最左端颜色,rc表示最右端颜色
     12 }T[MAXN << 2];
     13 int head[MAXN] , tot;
     14 int son[MAXN] , size[MAXN] , par[MAXN] , dep[MAXN] , cnt;
     15 int top[MAXN] , id[MAXN] , fid[MAXN];
     16 int a[MAXN];
     17 
     18 void init() {
     19     memset(head , -1 , sizeof(head));
     20     tot = cnt = 0;
     21 }
     22 
     23 inline void add(int u , int v) {
     24     edge[tot].next = head[u];
     25     edge[tot].to = v;
     26     head[u] = tot++;
     27 }
     28 
     29 void dfs1(int u , int p , int d) {
     30     dep[u] = d , size[u] = 1 , son[u] = u , par[u] = p;
     31     for(int i = head[u] ; ~i ; i = edge[i].next) {
     32         int v = edge[i].to;
     33         if(v == p)
     34             continue;
     35         dfs1(v , u , d + 1);
     36         if(size[v] >= size[son[u]])
     37             son[u] = v;
     38         size[u] += size[v];
     39     }
     40 }
     41 
     42 void dfs2(int u , int p , int t) {
     43     top[u] = t , id[u] = ++cnt;
     44     fid[cnt] = u;
     45     if(son[u] != u)
     46         dfs2(son[u] , u , t);
     47     for(int i = head[u] ; ~i ; i = edge[i].next) {
     48         int v = edge[i].to;
     49         if(v == p || v == son[u])
     50             continue;
     51         dfs2(v , u , v);
     52     }
     53 }
     54 
     55 void pushdown(int p) {
     56     if(T[p].lazy != -1) {
     57         int ls = p << 1 , rs = (p << 1)|1;
     58         T[ls].rc = T[ls].lc = T[rs].lc = T[rs].rc = T[p].lazy;
     59         T[ls].lazy = T[rs].lazy = T[p].lazy;
     60         T[ls].sum = T[rs].sum = 1; //变成同一个颜色 sum就为1了
     61         T[p].lazy = -1;
     62     }
     63 }
     64 
     65 void pushup(int p) {
     66     T[p].lc = T[p << 1].lc , T[p].rc = T[(p << 1)|1].rc; //这里注意要回溯上来,父节点的左右端颜色要更新
     67     T[p].sum = T[p << 1].sum + T[(p << 1)|1].sum - (T[p << 1].rc == T[(p << 1)|1].lc); //合并操作:要是左孩子的最右端颜色等于右孩子最左端颜色,那就需要-1
     68 }
     69 
     70 void build(int p , int l , int r) {
     71     int mid = (l + r) >> 1;
     72     T[p].r = r , T[p].l = l , T[p].lc = a[fid[l]] , T[p].rc = a[fid[r]] , T[p].lazy = -1;
     73     if(l == r) {
     74         T[p].sum = 1;
     75         return ;
     76     }
     77     build(p << 1 , l , mid);
     78     build((p << 1)|1 , mid + 1 , r);
     79     pushup(p);
     80 }
     81 
     82 void update(int p , int l , int r , int color) {
     83     int mid = (T[p].l + T[p].r) >> 1;
     84     if(T[p].l == l && T[p].r == r) {
     85         T[p].sum = 1 , T[p].lazy = T[p].rc = T[p].lc = color;
     86         return ;
     87     }
     88     pushdown(p);
     89     if(r <= mid) {
     90         update(p << 1 , l , r , color);
     91     }
     92     else if(l > mid) {
     93         update((p << 1)|1 , l , r , color);
     94     }
     95     else {
     96         update(p << 1 , l , mid , color);
     97         update((p << 1)|1 , mid + 1 , r , color);
     98     }
     99     pushup(p);
    100 }
    101 
    102 int query(int p , int l , int r) {
    103     int mid = (T[p].l + T[p].r) >> 1;
    104     if(T[p].l == l && T[p].r == r) {
    105         return T[p].sum;
    106     }
    107     pushdown(p);
    108     if(r <= mid) {
    109         return query(p << 1 , l , r);
    110     }
    111     else if(l > mid) {
    112         return query((p << 1)|1 , l , r);
    113     }
    114     else {
    115         return query(p << 1 , l , mid) + query((p << 1)|1 , mid + 1 , r) - (T[p << 1].rc == T[(p << 1)|1].lc);
    116     }
    117 }
    118 
    119 int query_pos_color(int p , int pos) {
    120     int mid = (T[p].l + T[p].r) >> 1;
    121     if(T[p].l == T[p].r && pos == T[p].r) {
    122         return T[p].lc;
    123     }
    124     pushdown(p);
    125     if(pos <= mid) {
    126         query_pos_color(p << 1 , pos);
    127     }
    128     else {
    129         query_pos_color((p << 1)|1 , pos);
    130     }
    131 }
    132 
    133 void find_update(int u , int v , int val) {
    134     int fu = top[u] , fv = top[v];
    135     while(fu != fv) {
    136         if(dep[fu] >= dep[fv]) {
    137             update(1 , id[fu] , id[u] , val);
    138             u = par[fu];
    139             fu = top[u];
    140         }
    141         else {
    142             update(1 , id[fv] , id[v] , val);
    143             v = par[fv];
    144             fv = top[v];
    145         }
    146     }
    147     if(dep[u] > dep[v])
    148         update(1 , id[v] , id[u] , val);
    149     else
    150         update(1 , id[u] , id[v] , val);
    151 }
    152 
    153 int find_ans(int u , int v) {
    154     int fu = top[u] , fv = top[v] , res = 0;
    155     while(fu != fv) {
    156         if(dep[fu] >= dep[fv]) {
    157             res += query(1 , id[fu] , id[u]);
    158             if(query_pos_color(1 , id[fu]) == query_pos_color(1 , id[par[fu]])) //要是fu节点和其父节点颜色相同就-1
    159                 res--;
    160             u = par[fu];
    161             fu = top[u];
    162         }
    163         else {
    164             res += query(1 , id[fv] , id[v]); 
    165             if(query_pos_color(1 , id[fv]) == query_pos_color(1 , id[par[fv]])) //上同
    166                 res--;
    167             v = par[fv];
    168             fv = top[v];
    169         }
    170     }
    171     if(dep[u] > dep[v]) {
    172         res += query(1 , id[v] , id[u]);
    173         return res;
    174     }
    175     else {
    176         res += query(1 , id[u] , id[v]);
    177         return res;
    178     }
    179 } 
    180 
    181 int main()
    182 {
    183     int n , m , u , v , val;
    184     char q[5];
    185     while(~scanf("%d %d" , &n , &m)) {
    186         init();
    187         for(int i = 1 ; i <= n ; ++i)
    188             scanf("%d" , a + i);
    189         for(int i = 1 ; i < n ; ++i) {
    190             scanf("%d %d" , &u , &v);
    191             add(u , v);
    192             add(v , u);
    193         }
    194         dfs1(1 , 1 , 0);
    195         dfs2(1 , 1 , 1);
    196         build(1 , 1 , cnt);
    197         while(m--) {
    198             scanf("%s" , q);
    199             if(q[0] == 'Q') {
    200                 scanf("%d %d" , &u , &v);
    201                 printf("%d
    " , find_ans(u , v));
    202             }
    203             else {
    204                 scanf("%d %d %d" , &u , &v , &val);
    205                 find_update(u , v , val);
    206             }
    207         }
    208     }
    209     return 0;
    210 }
  • 相关阅读:
    MT【319】分段递推数列
    MT【318】分式不等式双代换
    Centos7环境变量
    VI快捷键
    Centos7 开机自动运行命令
    Centos7 编辑本地DNS解析配置文件
    Centos7修改主机名
    xadmin 自定义过滤器选项
    Centos7网卡配置文件
    Centos7 挂载
  • 原文地址:https://www.cnblogs.com/Recoder/p/5543047.html
Copyright © 2011-2022 走看看