Cod sursa(job #2956442)

Utilizator retrogradLucian Bicsi retrograd Data 19 decembrie 2022 15:58:22
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.49 kb
#include <bits/stdc++.h>

using namespace std;


struct HeavyPath {
  int n;
  struct BST { int son[2], par, depth, val, dp; };
  vector<BST> B;
  vector<vector<int>> graph; 
  vector<int> sub, heavy, path;

  HeavyPath(int n) : 
    n(n), B(n), graph(n), 
    sub(n), heavy(n), path(n) {}

  void Add(int a, int b) { 
    graph[a].push_back(b);
    graph[b].push_back(a);
  }
  int init(int from, int to, int par, int dep) {
    if (from == to) return -1;

    int root = -1, w = sub[from] - (to == -1 ? 0 : sub[to]);
    for (int x = from; x != to; x = heavy[x])
      if (sub[from] - sub[x] <= w/2)
        root = x;

    B[root].son[0] = init(from, root, root, dep + 1);
    B[root].son[1] = init(heavy[root], to, root, dep + 1);
    B[root].par = par;
    B[root].depth = dep;
    pull(root);

    for (auto vec : graph[root])
      if (vec != heavy[root] && sub[vec] < sub[root])
        init(vec, -1, root, dep + 100);

    return root;
  }
  void dfs(int node, int par) {
    sub[node] = 1; heavy[node] = -1;
    for (auto vec : graph[node]) {
      if (vec == par) continue;
      dfs(vec, node);
      sub[node] += sub[vec];
      if (heavy[node] == -1 || sub[heavy[node]] < sub[vec])
        heavy[node] = vec;
    }
    path[node] = heavy[node] == -1 ? node : path[heavy[node]];
  }

  void Build(int root) { 
    dfs(root, -1); 
    init(root, -1, -1, 0);
  }

  void pull(int x) {
    B[x].dp = B[x].val;
    for (int z : {B[x].son[0], B[x].son[1]})
      if (z != -1)
        B[x].dp = max(B[x].dp, B[z].dp);
  }
  void Update(int node, int val) {
    B[node].val = val;
    for (int x = node; x != -1 && path[x] == path[node]; x = B[x].par)
      pull(x);
  }
  int Query(int x, int y) {
    int ans = -2e9;
    while (x != y) {
      if (B[x].depth < B[y].depth) swap(x, y);
      ans = max(ans, B[x].val);
      int z = B[x].son[path[x] == path[y] && sub[x] > sub[y]];
      if (z != -1) ans = max(ans, B[z].val);
      while (path[x] != path[y] && sub[x] > sub[B[x].par]) 
        x = B[x].par;
      x = B[x].par;
    }
    ans = max(ans, B[x].val);
    return ans;
  }
};

int main() {
  ifstream cin("heavypath.in");
  ofstream cout("heavypath.out");
  int n, q; cin >> n >> q;
  HeavyPath H(n);
  for (int i = 0; i < n; ++i) {
    cin >> H.B[i].val;
  }
  for (int i = 1; i < n; ++i) {
    int a, b; cin >> a >> b;
    H.Add(a - 1, b - 1);
  }
  H.Build(0);
  for (int i = 0; i < q; ++i) {
    int t, x, y; cin >> t >> x >> y;
    if (t == 0) H.Update(x - 1, y);
    else cout << H.Query(x - 1, y - 1) << '\n'; 
  }

  return 0;
}