zoukankan      html  css  js  c++  java
  • [SDOI2017]树点涂色

    题意

    有操作:

    • 1 $x$

    把点 $x到根节点的路径上所有的点染上一种没有用过的新颜色。

    • 2 $x$ $y$

    求 $x到 $y的路径的权值。

    • 3 $x$

    在以 $x$ 为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。

    题解

    因为观察到一个颜色一定是一条向根节点的链,也就是说一条链代表了一个信息,那么就可以用 $LCT$ 中的一个 $Splay$ 去维护一条链(颜色)

    那么一个节点的“权值”即为它到根节点经过的轻边个数,求出单点“权值”后,直接用差分即可解决操作 $2$

    用树剖可以解决,但是这样的话连 $LCT$ 都不用了,同理,想到 $dfs$ 序,在 $Access$ 操作的时候删掉一条轻边并且增加一条轻边,答案有修改的只有该轻边端点包含的子树,那么直接线段树修改就好了

    代码

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 
      5 #define lson root << 1
      6 #define rson root << 1 | 1
      7 
      8 using namespace std;
      9 
     10 const int MAXN = 1e05 + 10;
     11 const int MAXM = 1e05 + 10;
     12 
     13 struct LinkedForwardStar {
     14     int to;
     15 
     16     int next;
     17 } ;
     18 
     19 LinkedForwardStar Link[MAXM << 1];
     20 int Head[MAXN]= {0};
     21 int size = 0;
     22 
     23 void Insert (int u, int v) {
     24     Link[++ size].to = v;
     25     Link[size].next = Head[u];
     26 
     27     Head[u] = size;
     28 }
     29 
     30 const int Root = 1;
     31 
     32 int Deep[MAXN];
     33 int Size[MAXN]= {0};
     34 int Dfn[MAXN], Rank[MAXN];
     35 int dfsord = 0;
     36 
     37 int Maxv[MAXN << 2]= {0};
     38 int lazy[MAXN << 2]= {0};
     39 void pushdown (int root) {
     40     if (lazy[root]) {
     41         Maxv[lson] += lazy[root];
     42         Maxv[rson] += lazy[root];
     43         lazy[lson] += lazy[root];
     44         lazy[rson] += lazy[root];
     45         lazy[root] = 0;
     46     }
     47 }
     48 void Build (int root, int left, int right) {
     49     if (left == right) {
     50         Maxv[root] = Deep[Rank[left]];
     51         return ;
     52     }
     53     int mid = (left + right) >> 1;
     54     Build (lson, left, mid);
     55     Build (rson, mid + 1, right);
     56     Maxv[root] = max (Maxv[lson], Maxv[rson]);
     57 }
     58 void Modify (int root, int left, int right, int L, int R, int delta) {
     59     if (L <= left && right <= R) {
     60         Maxv[root] += delta;
     61         lazy[root] += delta;
     62         return ;
     63     }
     64     pushdown (root);
     65     int mid = (left + right) >> 1;
     66     if (L <= mid)
     67         Modify (lson, left, mid, L, R, delta);
     68     if (R >  mid)
     69         Modify (rson, mid + 1, right, L, R, delta);
     70     Maxv[root] = max (Maxv[lson], Maxv[rson]);
     71 }
     72 int Query (int root, int left, int right, int L, int R) {
     73     if (L <= left && right <= R)
     74         return Maxv[root];
     75     pushdown (root);
     76     int mid = (left + right) >> 1;
     77     int maxv = 0;
     78     if (L <= mid)
     79         maxv = max (maxv, Query (lson, left, mid, L, R));
     80     if (R > mid)
     81         maxv = max (maxv, Query (rson, mid + 1, right, L, R));
     82     return maxv;
     83 }
     84 
     85 int N, M;
     86 
     87 int father[MAXN]= {0};
     88 int son[MAXN][2]= {0};
     89 int isroot (int p) {
     90     return son[father[p]][0] != p && son[father[p]][1] != p;
     91 }
     92 int sonbel (int p) {
     93     return son[father[p]][1] == p;
     94 }
     95 void rotate (int p) {
     96     int fa = father[p], anc = father[fa];
     97     int s = sonbel (p);
     98     son[fa][s] = son[p][s ^ 1];
     99     if (son[fa][s])
    100         father[son[fa][s]] = fa;
    101     if (! isroot (fa))
    102         son[anc][sonbel (fa)] = p;
    103     father[p] = anc;
    104     son[p][s ^ 1] = fa, father[fa] = p;
    105 }
    106 void splay (int p) {
    107     for (int fa = father[p]; ! isroot (p); rotate (p), fa = father[p])
    108         if (! isroot (fa))
    109             sonbel (p) == sonbel (fa) ? rotate (fa) : rotate (p);
    110 }
    111 int findroot (int p) {
    112     while (son[p][0])
    113         p = son[p][0];
    114     return p;
    115 }
    116 void Access (int p) {
    117     for (int tp = 0; p; tp = p, p = father[p]) {
    118         splay (p);
    119         if (son[p][1]) {
    120             int rt = findroot (son[p][1]);
    121             Modify (Root, 1, N, Dfn[rt], Dfn[rt] + Size[rt] - 1, 1);
    122         }
    123         son[p][1] = tp;
    124         if (son[p][1]) {
    125             int rt = findroot (son[p][1]);
    126             Modify (Root, 1, N, Dfn[rt], Dfn[rt] + Size[rt] - 1, - 1);
    127         }
    128     }
    129 }
    130 
    131 int ances[MAXN][20];
    132 void DFS (int root, int fa) {
    133     Dfn[root] = ++ dfsord, Rank[dfsord] = root;
    134     ances[root][0] = father[root] = fa;
    135     for (int j = 1; j <= 18; j ++) {
    136         if (! ances[root][j - 1])
    137             break;
    138         ances[root][j] = ances[ances[root][j - 1]][j - 1];
    139     }
    140     Size[root] = 1;
    141     for (int i = Head[root]; i; i = Link[i].next) {
    142         int v = Link[i].to;
    143         if (v == fa)
    144             continue;
    145         Deep[v] = Deep[root] + 1;
    146         DFS (v, root);
    147         Size[root] += Size[v];
    148     }
    149 }
    150 
    151 int LCA (int x, int y) {
    152     if (Deep[x] < Deep[y])
    153         swap (x, y);
    154     int fx = x, fy = y;
    155     for (int j = 18; j >= 0; j --)
    156         if (Deep[ances[fx][j]] >= Deep[fy])
    157             fx = ances[fx][j];
    158     if (fx == fy)
    159         return fy;
    160     for (int j = 18; j >= 0; j --)
    161         if (ances[fx][j] != ances[fy][j]) {
    162             fx = ances[fx][j];
    163             fy = ances[fy][j];
    164         }
    165     return ances[fx][0];
    166 }
    167 
    168 int getnum () {
    169     int num = 0;
    170     char ch = getchar ();
    171 
    172     while (! isdigit (ch))
    173         ch = getchar ();
    174     while (isdigit (ch))
    175         num = (num << 3) + (num << 1) + ch - '0', ch = getchar ();
    176 
    177     return num;
    178 }
    179 
    180 int main () {
    181     N = getnum (), M = getnum ();
    182     for (int i = 1; i < N; i ++) {
    183         int u = getnum (), v = getnum ();
    184         Insert (u, v), Insert (v, u);
    185     }
    186     Deep[Root] = 1, DFS (Root, 0);
    187     Build (Root, 1, N);
    188     for (int i = 1; i <= M; i ++) {
    189         int opt = getnum ();
    190         if (opt == 1) {
    191             int p = getnum ();
    192             Access (p);
    193         }
    194         else if (opt == 2) {
    195             int x = getnum (), y = getnum ();
    196             int lca = LCA (x, y);
    197             int qx = Query (Root, 1, N, Dfn[x], Dfn[x]);
    198             int qy = Query (Root, 1, N, Dfn[y], Dfn[y]);
    199             int qlca = Query (Root, 1, N, Dfn[lca], Dfn[lca]);
    200             int ans = qx + qy - (qlca << 1) + 1;
    201             printf ("%d
    ", ans);
    202         }
    203         else if (opt == 3) {
    204             int p = getnum ();
    205             int ans = Query (Root, 1, N, Dfn[p], Dfn[p] + Size[p] - 1);
    206             printf ("%d
    ", ans);
    207         }
    208     }
    209 
    210     return 0;
    211 }
    212 
    213 /*
    214 5 6
    215 1 2
    216 2 3
    217 3 4
    218 3 5
    219 2 4 5
    220 3 3
    221 1 4
    222 2 4 5
    223 1 5
    224 2 4 5
    225 */
  • 相关阅读:
    交叉编译fw_printenv
    解压 xxxx.cpio.gz.u-boot
    创建Uboot 环境变量 bin 文件
    Linux快速显示图片
    移动终端的GPU显卡介绍
    Video Mode Timings
    change systemd service
    device tree DTB DTC 相互转换
    如何写出安全的API接口(参数加密+超时处理+私钥验证+Https)- 续(附demo)
    解决h5在ios 微信中 input框键盘收起 页面底部留白
  • 原文地址:https://www.cnblogs.com/Colythme/p/10218019.html
Copyright © 2011-2022 走看看