Cod sursa(job #2689464)

Utilizator retrogradLucian Bicsi retrograd Data 20 decembrie 2020 23:25:05
Problema Heavy Path Decomposition Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.4 kb
#include <bits/stdc++.h>

using namespace std;

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

  Splay(int n) : T(n) {}
  
  void push(int x) {
    if (x == -1) return;
    if (T[x].flip) {
      for (int y : {T[x].ch[0], T[x].ch[1]}) if (~y) 
        T[y].flip ^= 1;
      swap(T[x].ch[0], T[x].ch[1]);
      T[x].flip = false;
    }
  }
  void pull(int x) {
    T[x].path = T[x].val;
    for (int y : {T[x].ch[0], T[x].ch[1]}) if (~y) { 
      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);
    if (~y) T[y].p = x;
  }
  void splay(int x) {
    auto dir = [&](int x) {
      for (int p = T[x].p, z = 0; z < 2; ++z) 
      if ((~p) && T[p].ch[z] == x)
        return z;
      return -1;
    };
    auto 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;
    };
    /// 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
    while (~dir(x)) {
      int y = T[x].p, z = T[y].p, 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 = -1; (~u); v = u, u = T[u].p) {
      splay(u);
      T[u].ch[1] = v;
      pull(u);
    }
    splay(x);
    assert(T[x].ch[1] == -1);
  }
  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 = -1);
  }
};

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