Advertisement
erek1e

SPOJ - QTREE

Apr 24th, 2023
867
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.97 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. // Segment Tree
  6. struct Node {
  7.     int mx;
  8.     Node * left, * right;
  9.     void resetVal() {
  10.         if (left && right) mx = max(left->mx, right->mx);
  11.         else if (right) mx = right->mx;
  12.         else if (left) mx = left->mx;
  13.         else mx = 0;
  14.     }
  15.     void update(int l, int r, int index, int value) {
  16.         if (l+1 == r) {
  17.             mx = value;
  18.             return;
  19.         }
  20.         int mid = (l + r) / 2;
  21.         if (index < mid) {
  22.             if (!left) left = new Node();
  23.             left->update(l, mid, index, value);
  24.         } else {
  25.             if (!right) right = new Node();
  26.             right->update(mid, r, index, value);
  27.         }
  28.         resetVal();
  29.     }
  30.     int rangeMax(int l, int r, int ql, int qr) {
  31.         if (qr <= l || r <= ql) return 0;
  32.         if (ql <= l && r <= qr) return mx;
  33.         int mid = (l + r) / 2;
  34.         int L = (left ? left->rangeMax(l, mid, ql, qr) : 0);
  35.         int R = (right ? right->rangeMax(mid, r, ql, qr) : 0);
  36.         return max(L, R);
  37.     }
  38. };
  39.  
  40. struct HLD {
  41.     int n;
  42.     vector<int> parent, depth, heavyChild, chainHead, pos;
  43.     int subtree(int v, const vector<vector<int>> &g) {
  44.         int totalSubtree = 1, maxSubtreeSize = 0;
  45.         for (int c : g[v]) {
  46.             if (c != parent[v]) {
  47.                 parent[c] = v, depth[c] = depth[v]+1;
  48.                 int childSubtree = subtree(c, g);
  49.                 totalSubtree += childSubtree;
  50.                 if (childSubtree > maxSubtreeSize) {
  51.                     maxSubtreeSize = childSubtree;
  52.                     heavyChild[v] = c;
  53.                 }
  54.             }
  55.         }
  56.         return totalSubtree;
  57.     }
  58.     void decompose(int r, const vector<vector<int>> &g) {
  59.         int nextPos = 0;
  60.         function<void(int, int)> recur = [&](int v, int h) {
  61.             chainHead[v] = h, pos[v] = nextPos++;
  62.             if (heavyChild[v] != -1) recur(heavyChild[v], h);
  63.             for (int c : g[v]) {
  64.                 if (c != parent[v] && c != heavyChild[v]) recur(c, c);
  65.             }
  66.         };
  67.         recur(r, r);
  68.     }
  69.  
  70.     // Segment Tree on max edge to parent in range
  71.     Node * root;
  72.  
  73.     void build(const vector<vector<int>> g) {
  74.         n = g.size();
  75.         parent = depth = chainHead = pos = vector<int>(n);
  76.         heavyChild.assign(n, -1);
  77.  
  78.         subtree(0, g);
  79.         decompose(0, g);
  80.  
  81.         root = new Node();
  82.     }
  83.     void updateEdge(int a, int b, int w) { // updates edge from a to b to have weight w
  84.         if (parent[a] == b) swap(a, b);
  85.         root->update(0, n, pos[b], w);
  86.     }
  87.     int maxEdge(int a, int b) { // on path from a to b
  88.         int maxEdge = 0;
  89.         for (; chainHead[a] != chainHead[b]; b = parent[chainHead[b]]) {
  90.             if (depth[chainHead[a]] > depth[chainHead[b]]) swap(a, b);
  91.             maxEdge = max(maxEdge, root->rangeMax(0, n, pos[chainHead[b]], pos[b]+1)); // including both head and b
  92.         }
  93.         if (depth[a] > depth[b]) swap(a, b);
  94.         maxEdge = max(maxEdge, root->rangeMax(0, n, pos[a]+1, pos[b]+1)); // excluding a because it's edge to parent is not on the path
  95.         return maxEdge;
  96.     }
  97. };
  98.  
  99. int main() {
  100.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  101.     int t; cin >> t;
  102.     while (t--) {
  103.         int n; cin >> n;
  104.         vector<int> a(n-1), b(n-1), c(n-1); // edge from a to b has cost c
  105.         vector<vector<int>> g(n);
  106.         for (int i = 0; i < n-1; ++i) {
  107.             cin >> a[i] >> b[i] >> c[i];
  108.             --a[i], --b[i];
  109.             g[a[i]].push_back(b[i]);
  110.             g[b[i]].push_back(a[i]);
  111.         }
  112.  
  113.         HLD d;
  114.         d.build(g);
  115.         for (int i = 0; i < n-1; ++i) d.updateEdge(a[i], b[i], c[i]);
  116.         string s;
  117.         while (cin >> s && s != "DONE") {
  118.             int x, y; cin >> x >> y;
  119.             if (s == "CHANGE") d.updateEdge(a[x-1], b[x-1], y);
  120.             else cout << d.maxEdge(x-1, y-1) << '\n';
  121.         }
  122.     }
  123.     return 0;
  124. }
  125.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement