• 树上莫队


    首先有一道题

    王室联邦

    题目大意

    给定一棵树,将树分为大小范围为 $[B, 3B]$ 的连通块集,求方案

    树上分块方法之一

    类似贪心,用栈维护还没有在连通块中的子节点,对于递归到的当前的点 $p$ ,扫描它的子树,能拼凑就拼凑

    但是注意最后可能还会有一些点(一定包括根)剩下,那么将这些点并到最后一个连通块即可

    显然每个连通块都满足大小为 $[B, 3B]$

    核心代码

    void DFS (int root, int father) {
        int bot = top;
        for (int i = Head[root]; i; i = Link[i].next) {
            int v = Link[i].to;
            if (v == father)
                continue;
            DFS (v, root);
            if (top - bot >= B) {
                capt[++ bind] = root;
                while (top > bot)
                    belong[Stack[top --]] = bind;
            }
        }
        Stack[++ top] = root;
    }

    树上莫队

    首先用王室联邦的方法将树分块

    用一个数组 $state_p$ 来维护 $p$ 点是否在当前询问的路径上,那么每次访问就将 $state_p$ 翻转,顺便修改 $ans$ ,相当于原序列上莫队的 $add, del$ 操作

    那么,每次需要修改那些点呢?

    假设当前处理到 $(px, py)$ ,现在需要处理 $(x, y)$ ,那么只需修改 $px$ 到 $x$ 以及 $py$ 到 $y$ 的路径上的点即可

    接下来证明该操作的正确性:

    令 $T (x, y)$ 表示 $x$ 到 $y$ 路径上的点集, $xor$ 操作类似位运算的异或,即有相同点则删去,无则加入

    则有 $T (x, y) = T (x, root) xor T (y, root)$ (注意,这里的 $T (x, y)$ 是不包括 $lca$ 的,故 $lca$ 需单独处理

    接下来是证明

    $egin{aligned} &T (px, py) xor T (x, y) \ &= [T (px, root) xor T (py, root)] xor [T (x, root) xor T (y, root)] \ &=  [T (px, root) xor T (x, root)] xor [T (py, root) xor T (y, root)] \ &= T (px, x) xor T (py, y) end{aligned}$

    那么其它的修改什么的就和序列上莫队一样了

    例题

    [WC2013]糖果公园

    代码

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cmath>
      6 
      7 using namespace std;
      8 
      9 typedef long long LL;
     10 
     11 const int MAXN = 1e05 + 10;
     12 const int MAXM = 1e05 + 10;
     13 const int MAXQ = 1e05 + 10;
     14 
     15 struct LinkedForwardStar {
     16     int to;
     17 
     18     int next;
     19 } ;
     20 
     21 LinkedForwardStar Link[MAXM << 1];
     22 int Head[MAXN]= {0};
     23 int size = 0;
     24 
     25 void Insert (int u, int v) {
     26     Link[++ size].to = v;
     27     Link[size].next = Head[u];
     28 
     29     Head[u] = size;
     30 }
     31 
     32 int N, M, Q;
     33 LL V[MAXN], W[MAXN];
     34 int pcol[MAXN];
     35 int limit;
     36 
     37 int belong[MAXN];
     38 int lind = 0;
     39 int Stack[MAXN];
     40 int top = 0;
     41 void DFS_bel (int root, int father) {
     42     int bot = top;
     43     for (int i = Head[root]; i; i = Link[i].next) {
     44         int v = Link[i].to;
     45         if (v == father)
     46             continue;
     47         DFS_bel (v, root);
     48         if (top - bot >= limit) {
     49             lind ++;
     50             while (top > bot)
     51                 belong[Stack[top --]] = lind;
     52         }
     53     }
     54     Stack[++ top] = root;
     55 }
     56 
     57 int father[MAXN]= {0};
     58 int deep[MAXN];
     59 int dfn[MAXN];
     60 int value[MAXN << 1], ranking[MAXN << 1];
     61 int dfsord = 0;
     62 void DFS_LCA (int root, int fa) {
     63     father[root] = fa;
     64     dfn[root] = ++ dfsord;
     65     value[dfsord] = deep[root], ranking[dfsord] = root;
     66     for (int i = Head[root]; i; i = Link[i].next) {
     67         int v = Link[i].to;
     68         if (v == fa)
     69             continue;
     70         deep[v] = deep[root] + 1;
     71         DFS_LCA (v, root);
     72         value[++ dfsord] = deep[root], ranking[dfsord] = root;
     73     }
     74 }
     75 pair<int, int> ST[MAXN << 1][20];
     76 void RMQ () {
     77     for (int i = 1; i <= dfsord; i ++)
     78         ST[i][0] = make_pair (value[i], ranking[i]);
     79     for (int j = 1; j <= 18; j ++)
     80         for (int i = 1; i + (1 << j) - 1 <= dfsord; i ++)
     81             ST[i][j] = ST[i][j - 1].first < ST[i + (1 << (j - 1))][j - 1].first ? ST[i][j - 1] : ST[i + (1 << (j - 1))][j - 1];
     82 }
     83 int LCA (int x, int y) {
     84     int L = dfn[x], R = dfn[y];
     85     if (L > R)
     86         swap (L, R);
     87     int k = log2 (R - L + 1);
     88     return ST[L][k].first < ST[R - (1 << k) + 1][k].first ? ST[L][k].second : ST[R - (1 << k) + 1][k].second;
     89 }
     90 
     91 LL ans = 0;
     92 
     93 struct QuerySt {
     94     int index;
     95     int time;
     96     int x, y;
     97 
     98     QuerySt (int find = 0, int ftime = 0, int fx = 0, int fy = 0) :
     99         index (find), time (ftime), x (fx), y (fy) {}
    100 
    101     bool operator < (const QuerySt& p) const {
    102         if (belong[x] != belong[p.x])
    103             return belong[x] < belong[p.x];
    104         if (belong[y] != belong[p.y])
    105             return belong[y] < belong[p.y];
    106         return time < p.time;
    107     }
    108 } ;
    109 QuerySt Query[MAXQ];
    110 int qind = 0;
    111 int modposi[MAXQ], modtime[MAXQ];
    112 int modpre[MAXQ], modval[MAXQ];
    113 int mind = 0, cur = 0;
    114 int state[MAXN]= {0};
    115 int donet[MAXN]= {0};
    116 void reverse (int p) {
    117     if (state[p])
    118         ans -= V[pcol[p]] * W[donet[pcol[p]]], donet[pcol[p]] --;
    119     state[p] ^= 1;
    120     if (state[p])
    121         donet[pcol[p]] ++, ans += V[pcol[p]] * W[donet[pcol[p]]];
    122 }
    123 void move (int u, int v) {
    124     int lca = LCA (u, v);
    125     while (u != lca)
    126         reverse (u), u = father[u];
    127     while (v != lca)
    128         reverse (v), v = father[v];
    129 }
    130 void extime (int p, int type) {
    131     bool exist = false;
    132     if (state[modposi[p]]) {
    133         exist = true;
    134         reverse (modposi[p]);
    135     }
    136     if (type == 1) {
    137         modpre[p] = pcol[modposi[p]];
    138         pcol[modposi[p]] = modval[p];
    139     }
    140     else {
    141         pcol[modposi[p]] = modpre[p];
    142     }
    143     if (exist)
    144         reverse (modposi[p]);
    145 }
    146 void timemod (int ptime) {
    147     while (cur < mind && modtime[cur + 1] <= ptime)
    148         extime (++ cur, 1);
    149     while (cur > 0 && modtime[cur] > ptime)
    150         extime (cur --, 2);
    151 }
    152 LL answer[MAXQ]= {0};
    153 void Moqueue () {
    154     int px = 1, py = 1;
    155     for (int i = 1; i <= qind; i ++) {
    156         int ind = Query[i].index, time = Query[i].time;
    157         int x = Query[i].x, y = Query[i].y;
    158         timemod (time);
    159         move (px, x), px = x;
    160         move (py, y), py = y;
    161         int lca = LCA (px, py);
    162         reverse (lca);
    163         answer[ind] = ans;
    164         reverse (lca);
    165     }
    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 (), Q = getnum ();
    182     limit = (int) ceil (pow ((double) N, 2.0 / 3.0));
    183     for (int i = 1; i <= M; i ++)
    184         V[i] = (LL) getnum ();
    185     for (int i = 1; i <= N; i ++)
    186         W[i] = (LL) getnum ();
    187     for (int i = 1; i < N; i ++) {
    188         int u = getnum (), v = getnum ();
    189         Insert (u, v), Insert (v, u);
    190     }
    191     for (int i = 1; i <= N; i ++)
    192         pcol[i] = getnum ();
    193     DFS_bel (1, 0);
    194     while (top > 0)
    195         belong[Stack[top --]] = lind;
    196     DFS_LCA (1, 0), RMQ ();
    197     for (int i = 1; i <= Q; i ++) {
    198         int opt = getnum ();
    199         if (opt == 0) {
    200             int p = getnum (), col = getnum ();
    201             modposi[++ mind] = p, modtime[mind] = i, modval[mind] = col;
    202         }
    203         else if (opt == 1) {
    204             int x = getnum (), y = getnum ();
    205             qind ++, Query[qind] = (QuerySt (qind, i, x, y));
    206         }
    207     }
    208     sort (Query + 1, Query + qind + 1);
    209     Moqueue ();
    210     for (int i = 1; i <= qind; i ++)
    211         printf ("%lld
    ", answer[i]);
    212 
    213     return 0;
    214 }
    215 
    216 /*
    217 4 3 5
    218 1 9 2
    219 7 6 5 1
    220 2 3
    221 3 1
    222 3 4
    223 1 2 3 2
    224 1 1 2
    225 1 4 2
    226 0 2 1
    227 1 1 2
    228 1 4 2
    229 */
  • 相关阅读:
    Knative Serving 进阶: Knative Serving SDK 开发实践
    从求生存到修体系,我在阿里找到了技术人的成长模式
    K8s 学习者绝对不能错过的最全知识图谱(内含 56个知识点链接)
    P1197 [JSOI2008]星球大战
    P1311 选择客栈
    P2822 组合数问题
    贪心 加工生产调度
    P3375 【模板】KMP字符串匹配
    P1025 数的划分
    P1019 单词接龙
  • 原文地址:https://www.cnblogs.com/Colythme/p/10243551.html
Copyright © 2020-2023  润新知