danielvitor23

Observing the Tree

May 31st, 2023
1,100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.86 KB | Source Code | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. typedef int64_t i64;
  5.  
  6. const int SIZE = 2e5+5;
  7.  
  8. struct Info {
  9.   int l, r;
  10.   i64 a, b;
  11.   Info (int l, int r, i64 a, i64 b) : l(l), r(r), a(a), b(b) {}
  12. };
  13.  
  14.  
  15. int64_t l[SIZE << 2], r[SIZE << 2], st[SIZE << 2], NODES = 0;
  16.  
  17. bool hasFlag[SIZE << 2];
  18. vector<Info> flag[SIZE << 2];
  19.  
  20. int newLeaf(int value) {
  21.   int p = ++NODES;
  22.   l[p] = r[p] = 0;
  23.   st[p] = value;
  24.   return p;
  25. }
  26.  
  27. int newParent(int lef, int rig) {
  28.   int p = ++NODES;
  29.   l[p] = lef;
  30.   r[p] = rig;
  31.   st[p] = st[lef] + st[rig];
  32.   return p;
  33. }
  34.  
  35. int newLazyKid(int node, int a, int b, int ul, int ur, int L, int R);
  36.  
  37. void propagate(int node, int L, int R) {
  38.   if (hasFlag[node]) {
  39.     if (L != R) {
  40.       for (auto info : flag[node]) {
  41.         int M = L+(R-L)/2;
  42.         l[node] = newLazyKid(l[node], info.a, info.b, info.l, info.r, L, M);
  43.         r[node] = newLazyKid(r[node], info.a, info.b, info.l, info.r, M + 1, R);
  44.       }
  45.       flag[node].clear();
  46.     }
  47.     hasFlag[node] = false;
  48.   }
  49. }
  50.  
  51. int newLazyKid(int node, int a, int b, int ul, int ur, int L, int R) {
  52.   int p = ++NODES;
  53.   l[p] = l[node];
  54.   r[p] = r[node];
  55.   flag[p] = flag[node];
  56.   hasFlag[p] = true;
  57.  
  58.   flag[p].push_back(Info(ul, ur, a, b));
  59.  
  60.   int64_t left = L, right = R;
  61.   int64_t A = a + (int64_t)b * (L - ul);
  62.  
  63.   st[p] = st[node] + (int64_t)A * (right - left + 1) + (int64_t)b * (right - left) * (right - left + 1) / 2;
  64.  
  65.   return p;
  66. }
  67.  
  68. int build(int L, int R) {
  69.   if (L == R) return newLeaf(0);
  70.   int M = L+(R-L)/2;
  71.   return newParent(build(L, M), build(M+1, R));
  72. }
  73.  
  74. int update(int node, int L, int R, int ul, int ur, int64_t a, int64_t b) {
  75.   if (ur < L or R < ul) return node;
  76.   if (ul <= L and R <= ur) return newLazyKid(node, a, b, ul, ur, L, R);
  77.   int M = L+(R-L)/2;
  78.   propagate(node, L, R);
  79.   return newParent(update(l[node], L, M, ul, ur, a, b),
  80.                    update(r[node], M + 1, R, ul, ur, a, b));
  81. }
  82.  
  83. int64_t query(int node, int L, int R, int a, int b) {
  84.   if (b < L || R < a)   return 0;
  85.   if (a <= L && R <= b) return st[node];
  86.   int M = L+(R-L)/2;
  87.   propagate(node, L, R);
  88.   return query(l[node], L, M, a, b) +
  89.          query(r[node], M + 1, R, a, b);
  90. }
  91.  
  92. int n, m;
  93. vector<vector<int>> gr;
  94.  
  95. int timer;
  96. vector<int> h, pos, sz, dad;
  97.  
  98. void dfs(int u, int par = -1) {
  99.   sz[u] = 1;
  100.   for (int &to : gr[u]) if (to != par) {
  101.     dad[to] = u;
  102.     dfs(to, u);
  103.     sz[u] += sz[to];
  104.     if (sz[to] > sz[gr[u][0]] or gr[u][0] == par)
  105.       swap(gr[u][0], to);
  106.   }
  107. }
  108.  
  109. void build_hld(int u, int par = -1) {
  110.   pos[u] = ++timer;
  111.   for (int to : gr[u]) if (to != par) {
  112.     h[to] = (to == gr[u][0] ? h[u] : to);
  113.     build_hld(to, u);
  114.   }
  115. }
  116.  
  117. int currentRoot = -1;
  118.  
  119. int64_t query_path(int a, int b) {
  120.   if (pos[a] < pos[b]) swap(a, b);
  121.  
  122.   if (h[a] == h[b]) return query(currentRoot, 1, n, pos[b], pos[a]);
  123.  
  124.   return query(currentRoot, 1, n, pos[h[a]], pos[a]) + query_path(dad[h[a]], b);
  125. }
  126.  
  127. void iterative_update_path(int a, int b, int64_t ai, int64_t r) {
  128.   for(;;) {
  129.     if (h[a] != h[b]) {
  130.       // chain distintas
  131.       if (pos[a] < pos[b]) {
  132.         // sobe o b
  133.         currentRoot = update(currentRoot, 1, n, pos[h[b]], pos[b], ai, r);
  134.         b = dad[h[b]];
  135.       } else if (pos[b] < pos[a]) {
  136.         // sobe o a
  137.         currentRoot = update(currentRoot, 1, n, pos[h[a]], pos[a], ai, r);
  138.         a = dad[h[a]];
  139.       }
  140.     } else {
  141.       // mesma chain
  142.       if (pos[a] < pos[b]) {
  143.         // sobe o b
  144.         currentRoot = update(currentRoot, 1, n, pos[a], pos[b], ai, r);
  145.         break;
  146.       } else if (pos[b] < pos[a]) {
  147.         // sobe o a
  148.         currentRoot = update(currentRoot, 1, n, pos[b], pos[a], ai, r);
  149.         break;
  150.       }
  151.     }
  152.   }
  153. }
  154.  
  155. int main() {
  156.   cin.tie(0)->sync_with_stdio(0);
  157.  
  158.   cin >> n >> m;
  159.  
  160.   gr.assign(n, vector<int>());
  161.   h.assign(n, 0);
  162.   pos.assign(n, 0);
  163.   sz.assign(n, 0);
  164.   dad.assign(n, -1);
  165.  
  166.   for (int i = 0; i < n-1; ++i) {
  167.     int a, b; cin >> a >> b, --a, --b;
  168.     gr[a].push_back(b);
  169.     gr[b].push_back(a);
  170.   }
  171.  
  172.   dfs(0, -1);
  173.   build_hld(0, -1);
  174.  
  175.   int firstRoot = build(1, n);
  176.   currentRoot = firstRoot;
  177.  
  178.   vector<int> roots{ currentRoot };
  179.  
  180.   int64_t lastAns = 0;
  181.   int cntChanges = 0;
  182.   while (m--) {
  183.     char op; cin >> op;
  184.  
  185.     if (op == 'c') {
  186.       int64_t x, y, a, b;
  187.       cin >> x >> y >> a >> b;
  188.       x = (x + lastAns) % n + 1;
  189.       y = (y + lastAns) % n + 1;
  190.  
  191.       --x; --y;
  192.  
  193.       ++cntChanges;
  194.       iterative_update_path(x, y, a, b);
  195.  
  196.       roots.push_back(currentRoot);
  197.     } else if (op == 'q') {
  198.       int64_t x, y; cin >> x >> y;
  199.       x = (x + lastAns) % n + 1;
  200.       y = (y + lastAns) % n + 1;
  201.  
  202.       --x; --y;
  203.  
  204.       lastAns = query_path(x, y);
  205.  
  206.       cout << lastAns << '\n';
  207.     } else if (op == 'l') {
  208.       int64_t x; cin >> x;
  209.       x = (x + lastAns) % (cntChanges + 1);
  210.       currentRoot = roots[x];
  211.     }
  212.   }
  213.  
  214. }
Advertisement
Add Comment
Please, Sign In to add comment