Cod sursa(job #3235355)

Utilizator LucaMuresanMuresan Luca Valentin LucaMuresan Data 17 iunie 2024 12:31:13
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.92 kb
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
#warning That's the baby, that's not my baby

typedef long long ll;

const int NMAX = 100'000;

std::vector<int> g[NMAX + 1];
int sz[NMAX + 1];
int depth[NMAX + 1];
int heavySon[NMAX + 1];
int a[NMAX + 1];
int parent[NMAX + 1];

void dfs(int u, int p = 0) {
  depth[u] = depth[p] + 1;
  parent[u] = p;
  sz[u] = 1;
  heavySon[u] = 0;
  for (const auto &v : g[u]) {
    if (v != p) {
      dfs(v, u);
      sz[u] += sz[v];
      if (sz[v] > sz[heavySon[u]]) {
        heavySon[u] = v;
      }
    }
  }
}

int head[NMAX + 1];
int paths;

int timer;

int label[NMAX + 1];
int tin[NMAX + 1];

void decomp(int u, int p = 0) {
  tin[u] = ++timer;
  if (heavySon[u] != 0) {
    decomp(heavySon[u], u);
    label[u] = label[heavySon[u]];
  } else {
    label[u] = ++paths;
  }
  head[label[u]] = u;
  for (const auto &v : g[u]) {
    if (v != p && v != heavySon[u]) {
      decomp(v, u);
    }
  }
}

struct segtree {
  std::vector<int> aint;
  int n;
  segtree() {}
  segtree(int _n) {
    n = _n;
    aint.resize(2 * n + 3, 0);
  }
  void update(int pos, const int &val) {
    for (aint[pos += n - 1] = val; pos > 1; pos >>= 1) {
      aint[pos >> 1] = std::max(aint[pos], aint[pos ^ 1]);
    }
  }
  int query(int l, int r) {
    assert(1 <= l);
    assert(l <= r);
    assert(r <= n);
    int ret = 0;
    for (l += n - 1, r += n; l < r; l >>= 1, r >>= 1) {
      if (l & 1) {
        ret = std::max(ret, aint[l++]);
      }
      if (r & 1) {
        ret = std::max(ret, aint[--r]);
      }
    }
    return ret;
  }
};

segtree aint;

int maxPath(int u, int v) {
  int ret = 0;
  while (label[u] != label[v]) {
    if (depth[head[label[u]]] > depth[head[label[v]]]) {
      ret = std::max(ret, aint.query(tin[u], tin[head[label[u]]]));
      u = parent[head[label[u]]];
    } else {
      ret = std::max(ret, aint.query(tin[v], tin[head[label[v]]]));
      v = parent[head[label[v]]];
    }
  }
  if (tin[u] > tin[v]) {
    std::swap(u, v);
  }
  ret = std::max(ret, aint.query(tin[u], tin[v]));
  return ret;
}

int main() {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(0);
  std::cout.tie(0);

  #ifndef LOCAL
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
  #endif

  int n, q;
  std::cin >> n >> q;

  for (int i = 1; i <= n; i++) {
    std::cin >> a[i];
  }
  for (int i = 1; i < n; i++) {
    int u, v;
    std::cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }

  dfs(1);
  decomp(1);

  aint = n;
  for (int i = 1; i <= n; i++) {
    tin[i] = n - tin[i] + 1;
    aint.update(tin[i], a[i]);
  }

  while (q--) {
    int type, x, y;
    std::cin >> type >> x >> y;
    if (type == 0) {
      aint.update(tin[x], y);
    } else {
      std::cout << maxPath(x, y) << '\n';
    }
  }

  return 0;
}