Cod sursa(job #3256523)

Utilizator popescu_georgePopescu George popescu_george Data 14 noiembrie 2024 19:48:20
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.42 kb
#include <bits/stdc++.h>

using namespace std;

struct Splay {
  struct Node {
    int ch[2] = {0, 0}, p = 0;
    int path, val = 0;      // Path aggregates
    bool flip = 0;          // Lazy tags
  };
  vector<Node> T;

  Splay(int n) : T(n + 1) {}

  void push(int x) {
    if (!x || !T[x].flip) return;
    for (int y : {T[x].ch[0], T[x].ch[1]})
      T[y].flip ^= 1;
    swap(T[x].ch[0], T[x].ch[1]);
    T[x].flip = 0;
  }
  void pull(int x) {
    T[x].path = T[x].val;
    for (int y : {T[x].ch[0], T[x].ch[1]})
      T[x].path = max(T[x].path, T[y].path);
  }

  void set(int x, int d, int y) {
    T[x].ch[d] = y, pull(x);
    T[y].p = x;
  }
  int dir(int x) {
    int p = T[x].p; if (!p) return -1;
    return T[p].ch[0] == x ? 0 : T[p].ch[1] == x ? 1 : -1;
  }
  void rotate(int x) {
    int y = T[x].p, z = T[y].p, dx = dir(x), dy = dir(y);
    set(y, dx, T[x].ch[!dx]); set(x, !dx, y);
    if (~dy) set(z, dy, x); else T[x].p = z;
  }
  void splay(int x) {
    /// Push lazy tags
    // static vector<int> stk;
    // for (stk.push_back(x); ~dir(x); stk.push_back(x = T[x].p));
    // while (stk.size()) push(x = stk.back()), stk.pop_back();
    /// Rotate up
    for (push(x); ~dir(x); ) {
      int y = T[x].p, z = T[y].p;
      push(z); push(y), push(x);
      int dx = dir(x), dy = dir(y);
      if (~dy) rotate(dx != dy ? x : y);
      rotate(x);
    }
  }
};

struct LinkCut : Splay {
  LinkCut(int n) : Splay(n) {}

  void access(int x) {
    for (int u = x, v = 0; u; v = u, u = T[u].p) {
      splay(u);
      T[u].ch[1] = v;
      pull(u);
    }
    splay(x);
    assert(T[x].ch[1] == 0);
  }
  void reroot(int u) { access(u); T[u].flip ^= 1; push(u); }

  void Link(int u, int v) {
    reroot(u); access(v);
    T[u].p = v;
  }
  void Cut(int u, int v) {
    reroot(u); access(v);
    set(v, 0, T[u].p = 0);
  }
};

int main() {
  ifstream cin("heavypath.in");
  ofstream cout("heavypath.out");
  int n, m; cin >> n >> m;
  LinkCut lc(n);
  for (int i = 1; i <= n; ++i) {
    cin >> lc.T[i].val;
    lc.pull(i);
  }
  for (int i = 1; i < n; ++i) {
    int a, b; cin >> a >> b;
    lc.Link(a, b);
  }
  for (int i = 0; i < m; ++i) {
    int t, x, y; cin >> t >> x >> y;
    if (t == 0) {
      lc.reroot(x); lc.T[x].val = y; lc.pull(x);
    } else {
      lc.reroot(x); lc.access(y);
      cout << lc.T[y].path << '\n';
    }
  }

  return 0;
}