Advertisement
Nelofus

DDP 模板(Top Tree)

Sep 24th, 2024 (edited)
11
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.45 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using i64 = long long;
  3.  
  4. template<typename Ta, typename Tb>
  5. inline void chkmax(Ta &a, const Tb &b) {if (a < b)  a = b;}
  6. template<typename Ta, typename Tb>
  7. inline void chkmin(Ta &a, const Tb &b) {if (a > b)  a = b;}
  8. constexpr int MEMORY_POOL = 1 << 20;
  9. char BUFFER[MEMORY_POOL], *PS = BUFFER, *PT = BUFFER;
  10. inline char gc() {
  11.     if (PS == PT)   PT = (PS = BUFFER) + fread(BUFFER, 1, MEMORY_POOL, stdin);
  12.     return PS == PT ? EOF : *PS++;
  13. }
  14. template<typename T>
  15. inline void read(T &ans) {
  16.     ans = 0;
  17.     T w = 1;
  18.     char c = gc();
  19.     while (!isdigit(c)) {
  20.         if (c == '-')   w = -1;
  21.         c = gc();
  22.     }
  23.     while (isdigit(c)) {
  24.         ans = (ans << 3) + (ans << 1) + (c ^ 48);
  25.         c = gc();
  26.     }
  27.     ans *= w;
  28. }
  29. template<typename T, typename ...Ts>
  30. void read(T &a, Ts&... other) {
  31.     read(a);
  32.     read(other...);
  33. }
  34.  
  35. char OUTB[MEMORY_POOL];
  36. char *P = OUTB;
  37. inline void flush() {fwrite(OUTB, 1, P - OUTB, stdout);P = OUTB;}
  38. inline void push(const char &x) {
  39.     if (P == OUTB + MEMORY_POOL)
  40.         flush();
  41.     *P++ = x;
  42. }
  43. inline void write(i64 x) {
  44.     if (x < 0)
  45.         x = -x, push('-');
  46.     static short stk[30], tt = 0;
  47.     do {
  48.         stk[tt++] = x % 10, x /= 10;
  49.     } while (x);
  50.     while (tt)
  51.         push(stk[--tt] + '0');
  52. }
  53.  
  54. constexpr int N = 1e6 + 10;
  55. constexpr int M = N << 1;
  56. constexpr int inf = 1e9;
  57.  
  58. template<typename T>
  59. inline void chkmax(T &a, const T &b) {if (a < b)    a = b;}
  60.  
  61. std::vector<int> G[N];
  62. int n, m;
  63. int w[N];
  64.  
  65. inline void add(int u, int v) {G[u].push_back(v);}
  66.  
  67. namespace TopTree {
  68.     struct Cluster {
  69.         int u, v;
  70.         int f[2][2];
  71.         int dis;
  72.         int siz;
  73.     };
  74.  
  75.     // b rake 到 a 上
  76.     inline Cluster Rake(const Cluster &a, const Cluster &b) {
  77.         Cluster res;
  78.         assert(a.u == b.u);
  79.  
  80.         res.u = a.u, res.v = a.v;
  81.         res.siz = a.siz + b.siz;
  82.         res.dis = a.dis;
  83.         for (int i = 0; i < 2; i++)
  84.             for (int j = 0; j < 2; j++) {
  85.                 res.f[i][j] = std::max(a.f[i][j] + w[b.v] + b.f[i][1], a.f[i][j] + b.f[i][0]);
  86.                 chkmax(res.f[i][j], -inf);
  87.             }
  88.         if (res.dis == 1)
  89.             res.f[1][1] = -inf;
  90.         return res;
  91.     }
  92.  
  93.     // a, b Compress
  94.     inline Cluster Compress(const Cluster &a, const Cluster &b) {
  95.         Cluster res;
  96.         assert(a.v == b.u);
  97.  
  98.         res.u = a.u, res.v = b.v;
  99.         res.siz = a.siz + b.siz;
  100.         res.dis = a.dis + b.dis;
  101.         for (int i = 0; i < 2; i++)
  102.             for (int j = 0; j < 2; j++) {
  103.                 res.f[i][j] = std::max(a.f[i][1] + w[a.v] + b.f[1][j], a.f[i][0] + b.f[0][j]);
  104.                 chkmax(res.f[i][j], -inf);
  105.             }
  106.         if (res.dis == 1)
  107.             res.f[1][1] = -inf;
  108.         return res;
  109.     }
  110.  
  111.     int totN;
  112.     struct node {
  113.         std::array<int, 2> ch;
  114.         Cluster info;
  115.         int fa, dep, type;   // type 0/1/2 分别为 base/rake/compress
  116.         int& operator [](const int &x) {
  117.             return ch[x];
  118.         }
  119.     } tr[M];
  120.  
  121.     inline void pull(int u) {
  122.         if (tr[u].type == 0)    return ;
  123.         tr[u].info = (tr[u].type == 1 ? Rake : Compress)(tr[tr[u][0]].info, tr[tr[u][1]].info);
  124.     }
  125.  
  126.     inline int merge(int u, int v, int type) {
  127.         totN++;
  128.         tr[totN][0] = u, tr[totN][1] = v;
  129.         tr[u].fa = totN, tr[v].fa = totN;
  130.         tr[totN].type = type;
  131.         pull(totN);
  132.         return totN;
  133.     }
  134.  
  135.     int Divide_And_Conquer(std::vector<int> &vec, int l, int r, int type) {
  136.         if (l == r)
  137.             return vec[l];
  138.         int gsum = 0;
  139.         for (int i = l; i <= r; i++)
  140.             gsum += tr[vec[i]].info.siz;
  141.  
  142.         int cur = 0, mid = r - 1;
  143.  
  144.         for (int i = l; i <= r - 1; i++) {
  145.             cur += tr[vec[i]].info.siz;
  146.             if (cur * 2 >= gsum) {
  147.                 mid = i;
  148.                 break;
  149.             }
  150.         }
  151.  
  152.         int ls = Divide_And_Conquer(vec, l, mid, type);
  153.         int rs = Divide_And_Conquer(vec, mid + 1, r, type);
  154.         return merge(ls, rs, type);
  155.     }
  156.  
  157.  
  158.     // 到 (u, fa[u]) 的基簇的 id
  159.     int fa_id[N];
  160.     int Ssiz[N], son[N], fa[N], dep[N];
  161.     void dfs_pre(int u) {
  162.         dep[u] = dep[fa[u]] + 1;
  163.         Ssiz[u] = 1;
  164.         for (const int &v : G[u]) {
  165.             if (v == fa[u])
  166.                 continue;
  167.             fa[v] = u;
  168.  
  169.             Cluster t;
  170.             t.u = u, t.v = v;
  171.             t.f[1][1] = -inf;
  172.             t.dis = 1, t.siz = 1;
  173.             tr[++totN] = {{0, 0}, t, 0, 0, 0};
  174.             fa_id[v] = totN;
  175.  
  176.             dfs_pre(v);
  177.             Ssiz[u] += Ssiz[v];
  178.             if (Ssiz[v] > Ssiz[son[u]])
  179.                 son[u] = v;
  180.         }
  181.     }
  182.  
  183.     int build(int tp) {
  184.         std::vector<int> seq;
  185.         if (fa_id[tp])
  186.             seq.push_back(fa_id[tp]);
  187.  
  188.         for (int u = tp; son[u]; u = son[u]) {
  189.             std::vector<int> seq2;
  190.             // 先把轻子树全部合并起来
  191.             for (const int &v : G[u]) {
  192.                 if (v == son[u] || v == fa[u])
  193.                     continue;
  194.                 seq2.push_back(build(v));
  195.             }
  196.  
  197.             if (!seq2.empty()) {
  198.                 int cur = fa_id[son[u]];
  199.                 // 分治 Rake 其他子树,然后 Rake 到重儿子上
  200.                 int out = Divide_And_Conquer(seq2, 0, (int)seq2.size() - 1, 1);
  201.                 seq.push_back(merge(cur, out, 1));
  202.             } else {
  203.                 seq.push_back(fa_id[son[u]]);
  204.             }
  205.         }
  206.         return Divide_And_Conquer(seq, 0, (int)seq.size() - 1, 2);
  207.     }
  208.    
  209.     int rt;
  210.     void dfs2(int u) {
  211.         tr[u].dep = tr[tr[u].fa].dep + 1;
  212.         if (tr[u].type)
  213.             dfs2(tr[u][0]), dfs2(tr[u][1]);
  214.     }
  215.     void re_update(int u) {
  216.         while (tr[u].fa)
  217.             u = tr[u].fa, pull(u);
  218.     }
  219.     void init(int n) {
  220.         dfs_pre(n);
  221.         rt = build(n);
  222.         dfs2(rt);
  223.     }
  224. };
  225.  
  226. using namespace TopTree;
  227.  
  228. int main() {
  229. #ifdef HeratinoNelofus
  230.     freopen("input.txt", "r", stdin);
  231. #endif
  232.  
  233.     read(n, m);
  234.     for (int i = 1; i <= n; i++)
  235.         read(w[i]);
  236.     for (int i = 1; i < n; i++) {
  237.         int u, v;
  238.         read(u, v);
  239.         add(u, v), add(v, u);
  240.     }
  241.     n++;
  242.     add(n, 1), add(1, n);
  243.     TopTree::init(n);
  244.     int lst = 0;
  245.     while (m--) {
  246.         int p, x;
  247.         read(p, x);
  248.         p ^= lst;
  249.         w[p] = x;
  250.         re_update(fa_id[p]);
  251.         auto t = tr[rt].info;
  252.         lst = std::max(t.f[0][1] + w[t.v], t.f[0][0]);
  253.         write(lst);
  254.         push('\n');
  255.     }
  256.     flush();
  257.     return 0;
  258. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement