Cod sursa(job #2700346)

Utilizator retrogradLucian Bicsi retrograd Data 27 ianuarie 2021 14:40:06
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.95 kb
// #include <debug.hpp>
#include <bits/stdc++.h>

using namespace std;

struct SegTree {
  vector<int> T; int n;
  SegTree(int n) : T(2 * n, (int)-2e9), n(n) {}
  
  void Update(int pos, int val) {
    for (T[pos += n] = val; pos > 1; pos /= 2)
      T[pos / 2] = max(T[pos], T[pos ^ 1]);
  }
  int Query(int b, int e) {
    int res = -2e9;
    for (b += n, e += n; b < e; b /= 2, e /= 2) {
      if (b % 2) res = max(res, T[b++]);
      if (e % 2) res = max(res, T[--e]);
    }
    return res;
  }
};

struct HeavyLight {
  int n, timer;
  vector<int> jump, sub, depth, enter, parent;
  
  HeavyLight(auto& graph, int root = 0) :
      n(graph.size()), jump(n), sub(n), 
      depth(n), enter(n), parent(n) {
    for (auto phase : {0, 1}) 
      timer = 0, dfs(graph, root, -1, 0, -1);
  }

  // Returns the position in the HL linearization
  int Get(int node) { return enter[node]; }
  // Runs a callback for all ranges [l, r] in the path 
  // a -> b. Some ranges might have l > r; if combining 
  // function is commutative just swap them.
  template<typename Callback>
  void QueryPath(int a, int b, Callback&& cb) {
    if (jump[a] == jump[b]) { 
      cb(enter[a], enter[b]); // (*)
    } else if (depth[jump[a]] > depth[jump[b]]) {
      cb(enter[a], enter[jump[a]]);
      QueryPath(parent[jump[a]], b, cb);
    } else {
      QueryPath(a, parent[jump[b]], cb);
      cb(enter[jump[b]], enter[b]);
    }
  }
  // Returns a range [l, r] corresponding to nodes in the
  // subtree.
  pair<int, int> QuerySubtree(int node) {
    return {enter[node], enter[node] + sub[node] - 1};
  }

  int dfs(auto& graph, int node, int par, int dep, int jmp) {
    if (jmp == -1) jmp = node;
    parent[node] = par; depth[node] = dep; jump[node] = jmp;
    enter[node] = timer++;
    int heavy = 0, ret = 1;
    for (auto& vec : graph[node]) {
      if (vec == par) continue;
      int now = dfs(graph, vec, node, dep + 1, jmp);
      if (heavy < now) heavy = now, swap(vec, graph[node][0]);
      ret += now; jmp = -1;
    }
    return sub[node] = ret;
  }
};

int main() {
  ifstream cin("heavypath.in");
  ofstream cout("heavypath.out");

  int n, q; cin >> n >> q;
  vector<int> v(n);
  for (int i = 0; i < n; ++i)
    cin >> v[i];
  vector<vector<int>> graph(n);
  for (int i = 1; i < n; ++i) {
    int a, b; cin >> a >> b; 
    graph[a - 1].push_back(b - 1);
    graph[b - 1].push_back(a - 1);
  }
  HeavyLight H(graph);
  // debug(H.depth);
  // debug(H.enter);
  // vector<int> order(n);
  // for (int i = 0; i < n; ++i)
  //   order[H.Get(i)] = i;
  
  // debug(order);

  SegTree st(n);
  for (int i = 0; i < n; ++i)
    st.Update(H.Get(i), v[i]);
  vector<pair<int, int>> ranges;
  for (int i = 0; i < q; ++i) {
    int t, a, b; cin >> t >> a >> b;
    if (t == 0) st.Update(H.Get(a - 1), b);
    else {
      int ans = -2e9;
      H.QueryPath(a - 1, b - 1, [&](int l, int r) {
        if (l > r) swap(l, r);
        ans = max(ans, st.Query(l, r + 1));
      });
      cout << ans << '\n';
    }
  }
  return 0;
}