zoukankan      html  css  js  c++  java
  • 洛谷P2486 染色

    LCT的一种姿势。

    题意:给定一棵树。每次把一条路径上的点染成一种颜色,求一条路径上有多少段颜色。

    解:

    首先可以很轻易的用树剖解决,只不过代码量让人望而却步...

    有一种难以想象的LCT做法...

    记录每个点的颜色,修改用lazy tag

    询问时把那一条链split出来,pushup的时候看当前点和前驱/后继的颜色是否相同。如果不同就sum++,表示有一条连接不同颜色点的边。

    最后的sum就是连接不同颜色的点的边数,再加1就是段数了。

      1 #include <cstdio>
      2 #include <algorithm>
      3 
      4 const int N = 100010;
      5 
      6 int fa[N], s[N][2], col[N], sum[N], lc[N], rc[N], S[N], Sp, tag[N];
      7 bool rev[N];
      8 
      9 inline bool no_root(int x) {
     10     return (s[fa[x]][0] == x) || (s[fa[x]][1] == x);
     11 }
     12 
     13 inline void pushdown(int x) {
     14     int ls = s[x][0], rs = s[x][1];
     15     if(rev[x]) {
     16         if(ls) {
     17             rev[ls] ^= 1;
     18             std::swap(lc[ls], rc[ls]);
     19         }
     20         if(rs) {
     21             rev[rs] ^= 1;
     22             std::swap(lc[rs], rc[rs]);
     23         }
     24         std::swap(s[x][0], s[x][1]);
     25         rev[x] = 0;
     26     }
     27     if(tag[x]) {
     28         int c = tag[x];
     29         if(ls) {
     30             tag[ls] = col[ls] = lc[ls] = rc[ls] = c;
     31             sum[ls] = 0;
     32         }
     33         if(rs) {
     34             tag[rs] = col[rs] = lc[rs] = rc[rs] = c;
     35             sum[rs] = 0;
     36         }
     37         tag[x] = 0;
     38     }
     39     return;
     40 }
     41 
     42 inline void pushup(int x) {
     43     int ls = s[x][0], rs = s[x][1];
     44     pushdown(ls);
     45     pushdown(rs);
     46     sum[x] = sum[ls] + sum[rs];
     47     if(ls) {
     48         lc[x] = lc[ls];
     49         if(rc[ls] != col[x]) {
     50             sum[x]++;
     51         }
     52     }
     53     else {
     54         lc[x] = col[x];
     55     }
     56     if(rs) {
     57         rc[x] = rc[rs];
     58         if(lc[rs] != col[x]) {
     59             sum[x]++;
     60         }
     61     }
     62     else {
     63         rc[x] = col[x];
     64     }
     65     return;
     66 }
     67 
     68 inline void rotate(int x) {
     69     int y = fa[x];
     70     int z = fa[y];
     71     bool f = (s[y][1] == x);
     72 
     73     fa[x] = z;
     74     if(no_root(y)) {
     75         s[z][s[z][1] == y] = x;
     76     }
     77     s[y][f] = s[x][!f];
     78     if(s[x][!f]) {
     79         fa[s[x][!f]] = y;
     80     }
     81     s[x][!f] = y;
     82     fa[y] = x;
     83 
     84     pushup(y);
     85     pushup(x);
     86     return;
     87 }
     88 
     89 inline void splay(int x) {
     90     int y = x;
     91     S[++Sp] = y;
     92     while(no_root(y)) {
     93         y = fa[y];
     94         S[++Sp] = y;
     95     }
     96     while(Sp) {
     97         pushdown(S[Sp]);
     98         Sp--;
     99     }
    100 
    101     y = fa[x];
    102     int z = fa[y];
    103     while(no_root(x)) {
    104         if(no_root(y)) {
    105             (s[z][1] == y) ^ (s[y][1] == x) ?
    106             rotate(x) : rotate(y);
    107         }
    108         rotate(x);
    109         y = fa[x];
    110         z = fa[y];
    111     }
    112     return;
    113 }
    114 
    115 inline void access(int x) {
    116     int y = 0;
    117     while(x) {
    118         splay(x);
    119         s[x][1] = y;
    120         pushup(x);
    121         y = x;
    122         x = fa[x];
    123     }
    124     return;
    125 }
    126 
    127 inline void make_root(int x) {
    128     access(x);
    129     splay(x);
    130     rev[x] = 1;
    131     return;
    132 }
    133 
    134 inline int find_root(int x) {
    135     access(x);
    136     splay(x);
    137     while(s[x][0]) {
    138         x = s[x][0];
    139         pushdown(x);
    140     }
    141     return x;
    142 }
    143 
    144 inline void link(int x, int y) {
    145     make_root(x);
    146     fa[x] = y;
    147     return;
    148 }
    149 
    150 inline void cut(int x, int y) {
    151     make_root(x);
    152     access(y);
    153     splay(y);
    154     fa[x] = s[y][0] = 0;
    155     pushup(y);
    156     return;
    157 }
    158 
    159 inline void change(int x, int y, int c) {
    160     make_root(x);
    161     access(y);
    162     splay(y);
    163     tag[y] = col[y] = lc[y] = rc[y] = c;
    164     sum[y] = 0;
    165     return;
    166 }
    167 
    168 inline int ask(int x, int y) {
    169     make_root(x);
    170     access(y);
    171     splay(y);
    172     return sum[y] + 1;
    173 }
    174 
    175 char str[10];
    176 
    177 int main() {
    178     int n, m;
    179     scanf("%d%d", &n, &m);
    180     for(int i = 1; i <= n; i++) {
    181         scanf("%d", &col[i]);
    182         lc[i] = rc[i] = col[i];
    183     }
    184     for(int i = 1, x, y; i < n; i++) {
    185         scanf("%d%d", &x, &y);
    186         link(x, y);
    187     }
    188 
    189     for(int i = 1, x, y, z; i <= m; i++) {
    190         scanf("%s%d%d", str, &x, &y);
    191         if(str[0] == 'C') {
    192             scanf("%d", &z);
    193             change(x, y, z);
    194         }
    195         else {
    196             int t = ask(x, y);
    197             printf("%d
    ", t);
    198         }
    199     }
    200 
    201     return 0;
    202 }
    AC代码

    有个简化版的问题:给定根,每次修改/询问必有一端点是根。有一种解法是,染色access,查询就看要跳多少个虚边。但是这样会被链卡成n²...不知道怎么改进。

  • 相关阅读:
    Rails组件逐个数:Rails Form helpers
    watirwebdriver常用方法
    Rails组件逐个数:Rails Form helpers(续)
    rails常用命令速查手册
    Rails new, build, create, save方法区别
    Ruby如何使用require从外部加载自定义类或模块
    升级Firefox8后watirwebdriver出现错误“unable to obtain stable firefox connection in 60 seconds”
    POJ2723Get Luffy Out(2sat)
    POJ3683Priest John's Busiest Day(2sat)
    UVA11374Airport Express(dijkstra)
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10170584.html
Copyright © 2011-2022 走看看