Cod sursa(job #3217018)

Utilizator smunteanuMunteanu Stefan Catalin smunteanu Data 20 martie 2024 19:05:43
Problema Heavy Path Decomposition Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.82 kb
#include <bits/stdc++.h>
using namespace std;

const int NMAX = 1e5 + 7;

int n, m;
int a[NMAX];
vector<int> adj[NMAX];

int pos[NMAX];
int par[NMAX];
int val[NMAX];
int head[NMAX];
int aint[NMAX];
int weight[NMAX];

void dfs(int u) {
  weight[u] = 1;
  for (int v : adj[u]) {
    if (v == par[u]) continue;
    par[v] = u;
    dfs(v);
    weight[u] += weight[v];
  }
}

void decomp(int u) {

  static int aint_pos = 0;
  pos[u] = aint_pos++;

  if (adj[u].empty() || (par[u] != 0 && adj[u].size() == 1)) return;
  
  int next = 0;
  for (int v : adj[u]) {
    if (v == par[u]) continue;
    next = weight[v] > weight[next] ? v : next;
  }

  head[next] = head[u];
  decomp(next);

  for (int v : adj[u]) {
    if (v == par[u] || v == next) continue;
    head[v] = v;
    decomp(v);
  }
}

void build(int b, int e, int i) {
  if (b == e) {
    aint[i] = val[b];
    return;
  }

  int m = (b + e) / 2;
  build(b, m, i * 2 + 1);
  build(m + 1, e, i * 2 + 2);
  aint[i] = max(aint[i * 2 + 1], aint[i * 2 + 2]);
}

void update(int b, int e, int i, int j, int v) {
  if (b == e) {
    aint[i] = v;
    return;
  }

  int m = (b + e) / 2;
  if (j <= m) update(b, m, i * 2 + 1, j, v);
  else update(m + 1, e, i * 2 + 2, j, v);
  aint[i] = max(aint[i * 2 + 1], aint[i * 2 + 2]);
}

int query(int b, int e, int i, int l, int r) {
  if (l <= b && e <= r) return aint[i];

  int m = (b + e) / 2;
  if (r <= m) return query(b, m, i * 2 + 1, l, r);
  if (l >= m + 1) return query(m + 1, e, i * 2 + 2, l, r);
  return max(query(b, m, i * 2 + 1, l, r), query(m + 1, e, i * 2 + 2, l, r));
}

void hld_update(int node, int value) {
  update(0, n - 1, 0, pos[node], value);
}

int hld_query(int node1, int node2) {
  int res = 0;
  while (head[node1] != head[node2]) {
    if (weight[head[node1]] > weight[head[node2]]) swap(node1, node2);
    res = max(res, query(0, n - 1, 0, pos[head[node1]], pos[node1]));
    node1 = par[head[node1]];
  }
  if (weight[node1] < weight[node2]) swap(node1, node2);
  return max(res, query(0, n - 1, 0, pos[node1], pos[node2]));
}

void solve() {
  
  cin >> n >> m;
  for (int i = 1; i <= n; i++) cin >> a[i];

  for (int i = 0; i < n - 1; i++) {
    int u, v;
    cin >> u >> v;
    adj[u].push_back(v);
    adj[v].push_back(u);
  }

  dfs(1);

  head[1] = 1;
  decomp(1);

  for (int i = 1; i <= n; i++) val[pos[i]] = a[i];

  build(0, n - 1, 0);

  for (int i = 0; i < m; i++) {
    int c, u, v;
    cin >> c >> u >> v;
    if (c == 0) hld_update(u, v);
    else cout << hld_query(u, v) << '\n';
  }
}

int main() {

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

  ios_base::sync_with_stdio(false), cin.tie(NULL);

  solve();
}