• 洛谷P3703 树点涂色


    题意:

    解:

    发现我们每次染的都是不同的颜色,那么用lct维护的话一个颜色就会在一个splay里。染色是access。

    维护每个节点到根路径上的虚边数量。

    虚边的切换只会在access和link中出现。于是access的时候顺便修改那个子树。lct上啥也不用维护。

    查询链可以用两端点减去lca。

      1 #include <bits/stdc++.h>
      2 
      3 const int N = 100010, INF = 0x3f3f3f3f;
      4 
      5 struct Edge {
      6     int nex, v;
      7 }edge[N << 1]; int tp;
      8 
      9 int e[N], n, siz[N], pos[N], id[N], d[N], num, top[N], father[N], son[N]; /// tree
     10 int fa[N], s[N][2], stk[N], Top; /// lct
     11 bool rev[N];
     12 int large[N << 2], tag[N << 2]; /// seg
     13 
     14 inline void add(int x, int y) {
     15     tp++;
     16     edge[tp].v = y;
     17     edge[tp].nex = e[x];
     18     e[x] = tp;
     19     return;
     20 }
     21 
     22 void DFS_1(int x, int f) { /// father siz son d
     23     siz[x] = 1;
     24     fa[x] = father[x] = f;
     25     for(int i = e[x]; i; i = edge[i].nex) {
     26         int y = edge[i].v;
     27         if(y == f) continue;
     28         d[y] = d[x] + 1;
     29         DFS_1(y, x);
     30         siz[x] += siz[y];
     31         if(siz[y] > siz[son[x]]) {
     32             son[x] = y;
     33         }
     34     }
     35     return;
     36 }
     37 
     38 void DFS_2(int x, int f) { /// top id pos
     39     top[x] = f;
     40     pos[x] = ++num;
     41     id[num] = x;
     42     if(son[x]) DFS_2(son[x], f);
     43     for(int i = e[x]; i; i = edge[i].nex) {
     44         int y = edge[i].v;
     45         if(y == father[x] || y == son[x]) continue;
     46         DFS_2(y, y);
     47     }
     48     return;
     49 }
     50 
     51 inline void Pushdown(int o) {
     52     if(tag[o]) {
     53         int ls = o << 1, rs = o << 1 | 1;
     54         tag[ls] += tag[o];
     55         tag[rs] += tag[o];
     56         large[ls] += tag[o];
     57         large[rs] += tag[o];
     58         tag[o] = 0;
     59     }
     60     return;
     61 }
     62 
     63 void build(int l, int r, int o) {
     64     if(l == r) {
     65         large[o] = d[id[r]];
     66         return;
     67     }
     68     int mid = (l + r) >> 1;
     69     build(l, mid, o << 1);
     70     build(mid + 1, r, o << 1 | 1);
     71     large[o] = std::max(large[o << 1], large[o << 1 | 1]);
     72     return;
     73 }
     74 
     75 void add(int L, int R, int v, int l, int r, int o) {
     76     if(L <= l && r <= R) {
     77         large[o] += v;
     78         tag[o] += v;
     79         return;
     80     }
     81     Pushdown(o);
     82     int mid = (l + r) >> 1;
     83     if(L <= mid) add(L, R, v, l, mid, o << 1);
     84     if(mid < R) add(L, R, v, mid + 1, r, o << 1 | 1);
     85     large[o] = std::max(large[o << 1], large[o << 1 | 1]);
     86     return;
     87 }
     88 
     89 int getMax(int L, int R, int l, int r, int o) {
     90     if(L <= l && r <= R) return large[o];
     91     int mid = (l + r) >> 1, ans = -INF;
     92     Pushdown(o);
     93     if(L <= mid) ans = std::max(ans, getMax(L, R, l, mid, o << 1));
     94     if(mid < R) ans = std::max(ans, getMax(L, R, mid + 1, r, o << 1 | 1));
     95     return ans;
     96 }
     97 
     98 int ask(int p, int l, int r, int o) {
     99     if(l == r) return large[o];
    100     Pushdown(o);
    101     int mid = (l + r) >> 1;
    102     if(p <= mid) return ask(p, l, mid, o << 1);
    103     else return ask(p, mid + 1, r, o << 1 | 1);
    104 }
    105 
    106 inline void pushdown(int x) {
    107     if(rev[x]) {
    108         std::swap(s[x][0], s[x][1]);
    109         if(s[x][0]) rev[s[x][0]] ^= 1;
    110         if(s[x][1]) rev[s[x][1]] ^= 1;
    111         rev[x] = 0;
    112     }
    113     return;
    114 }
    115 
    116 inline void pushup(int x) {
    117     return;
    118 }
    119 
    120 inline bool no_root(int x) {
    121     return (s[fa[x]][0] == x) || (s[fa[x]][1] == x);
    122 }
    123 
    124 inline void rotate(int x) {
    125     int y = fa[x];
    126     int z = fa[y];
    127     bool f = (s[y][1] == x);
    128 
    129     fa[x] = z;
    130     if(no_root(y)) {
    131         s[z][s[z][1] == y] = x;
    132     }
    133     s[y][f] = s[x][!f];
    134     if(s[x][!f]) {
    135         fa[s[x][!f]] = y;
    136     }
    137     s[x][!f] = y;
    138     fa[y] = x;
    139 
    140     pushup(y);
    141     return;
    142 }
    143 
    144 inline void splay(int x) {
    145     int y = x;
    146     stk[++Top] = y;
    147     while(no_root(y)) {
    148         y = fa[y];
    149         stk[++Top] = y;
    150     }
    151     while(Top) {
    152         pushdown(stk[Top]);
    153         Top--;
    154     }
    155 
    156     y = fa[x];
    157     int z = fa[y];
    158     while(no_root(x)) {
    159         if(no_root(y)) {
    160             (s[z][1] == y) ^ (s[y][1] == x) ?
    161             rotate(x) : rotate(y);
    162         }
    163         rotate(x);
    164         y = fa[x];
    165         z = fa[y];
    166     }
    167     pushup(x);
    168     return;
    169 }
    170 
    171 inline void change(int x, int v) {
    172     pushdown(x);
    173     while(s[x][0]) {
    174         x = s[x][0];
    175         pushdown(x);
    176     }
    177     /// x
    178     add(pos[x], pos[x] + siz[x] - 1, v, 1, n, 1);
    179     return;
    180 }
    181 
    182 inline void access(int x) {
    183     int y = 0;
    184     while(x) {
    185         splay(x);
    186         if(s[x][1]) change(s[x][1], 1);
    187         if(y) change(y, -1);
    188         s[x][1] = y;
    189         pushup(x);
    190         y = x;
    191         x = fa[x];
    192     }
    193     return;
    194 }
    195 
    196 inline int lca(int x, int y) {
    197     while(top[x] != top[y]) {
    198         if(d[top[x]] < d[top[y]]) {
    199             y = father[top[y]];
    200         }
    201         else {
    202             x = father[top[x]];
    203         }
    204     }
    205     return d[x] < d[y] ? x : y;
    206 }
    207 
    208 inline int ask(int x, int y) {
    209     //printf("ask : %d %d lca %d 
    ", x, y, lca(x, y));
    210     //printf("ask : %d + %d - 2 * %d 
    ", ask(pos[x], 1, n, 1), ask(pos[y], 1, n, 1), ask(pos[lca(x, y)], 1, n, 1));
    211     return ask(pos[x], 1, n, 1) + ask(pos[y], 1, n, 1) - 2 * ask(pos[lca(x, y)], 1, n, 1);
    212 }
    213 
    214 inline int query(int x) {
    215     return getMax(pos[x], pos[x] + siz[x] - 1, 1, n, 1);
    216 }
    217 
    218 int main() {
    219     int m;
    220     scanf("%d%d", &n, &m);
    221     for(int i = 1, x, y; i < n; i++) {
    222         scanf("%d%d", &x, &y);
    223         add(x, y); add(y, x);
    224     }
    225     /// init
    226     DFS_1(1, 0);
    227     DFS_2(1, 1);
    228     build(1, n, 1);
    229 
    230     for(int i = 1, f, x, y; i <= m; i++) {
    231         scanf("%d%d", &f, &x);
    232         if(f == 1) { /// change
    233             access(x);
    234         }
    235         else if(f == 2) {
    236             scanf("%d", &y);
    237             printf("%d
    ", ask(x, y) + 1);
    238         }
    239         else { /// f == 3
    240             printf("%d
    ", query(x) + 1);
    241         }
    242     }
    243     return 0;
    244 }
    AC代码
  • 相关阅读:
    Oracle修改数据文件路径
    检查交换空间: 可用的交换空间为 0 MB, 所需的交换空间为 150 MB。 未通过 <<<<
    Oracle 字符集修改
    Bad check value found during backing up datafileBad check value found during backing up datafile
    Oracle编译失效对象
    带where查询条件的expdp/impdp
    impdp导入报错案例ORA00907建表缺失右括号
    数据库参数 PGA_AGGREGATE_LIMIT 限制进程大小
    oracle本地服务名配置说明
    返回起始日期到终止日期的日期数据
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10482744.html
Copyright © 2020-2023  润新知