Cod sursa(job #2710548)

Utilizator retrogradLucian Bicsi retrograd Data 22 februarie 2021 18:18:37
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.52 kb
#include <bits/stdc++.h>
 
using namespace std;
 
struct SplayTree {
  struct Node {
    int ch[2] = {0, 0}, p = 0;
    int self = 0, path = 0; 
  };
  vector<Node> T;
 
  SplayTree(int n) : T(n + 1) {}
 
  void push(int x) {}
  void pull(int x) {
    int l = T[x].ch[0], r = T[x].ch[1]; push(l); push(r);
    T[x].path = max({T[l].path, T[x].self, T[r].path});
  }
  void set(int x, int d, int y) {
    T[x].ch[d] = y; T[y].p = x; pull(x);
  }
  void splay(int x) {
    auto 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;
    };
    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);
      T[x].p = z;
    };
    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 : SplayTree {
  LinkCut(int n) : SplayTree(n) {}
 
  int access(int x) {
    int u = x, v = 0;
    for (; u; v = u, u = T[u].p) {
      splay(u);
      int& ov = T[u].ch[1];
      ov = v; pull(u);
    }
    return splay(x), v;
  }
  // Rooted tree LCA. Returns 0 if u and v arent connected.
  int LCA(int u, int v) {
    if (u == v) return u;
    access(u); int ret = access(v);
    return T[u].p ? ret : 0;
  }
  // Query path [u..v].
  int Path(int u, int v) {
    int lca = LCA(u, v);
    int ret = T[lca].self;
    access(u); splay(lca);
    ret = max(ret, T[T[lca].ch[1]].path);
    access(v); splay(lca);
    ret = max(ret, T[T[lca].ch[1]].path);
    return ret;
  }
  // Update vertex with value v.
  void Update(int u, int v) {
    access(u); T[u].self = v; pull(u);
  }
};
 
int main() {
  ifstream cin("heavypath.in");
  ofstream cout("heavypath.out");

  int n, q; cin >> n >> q;
  LinkCut LC(n);
  for (int i = 1; i <= n; ++i) {
    int x; cin >> x;
    LC.Update(i, x);
  }
  vector<vector<int>> graph(n + 1);
  for (int i = 1; i < n; ++i) {
    int a, b; cin >> a >> b; 
    graph[a].push_back(b); graph[b].push_back(a);
  }
  {
    vector<int> q = {1};
    for (int i = 0; i < n; ++i) {
      int node = q[i];
      for (auto vec : graph[node]) {
        if (vec != LC.T[node].p) {
          LC.T[vec].p = node;
          q.push_back(vec);
        }
      }
    }
  }
 
  for (int i = 0; i < q; ++i) {
    int t, u, v; cin >> t >> u >> v;
    if (t == 0) 
      LC.Update(u, v);
    else
      cout << LC.Path(u, v) << '\n';
  }
  
  return 0;
}