Cod sursa(job #3181960)

Utilizator smunteanuMunteanu Stefan Catalin smunteanu Data 8 decembrie 2023 15:47:50
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.13 kb
#include <bits/stdc++.h>
using namespace std;


const int NMAX = 1e5 + 7;


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

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

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

void decomp(int u) {
  static int pos_cur = 0;

  pos[u] = ++pos_cur;
  if (par[u] && adj[u].size() == 1) return;

  int s = 0;
  for (int v : adj[u]) if (v != par[u] && weight[v] > weight[s]) s = v;

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

  for (int v : adj[u]) {
    if (v == s || v == par[u]) 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 solve() {
  
  int q;
  cin >> n >> q;

  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(1, n, 0);

  #ifdef LOCAL
  for (int i = 1; i <= n; i++) cout << head[i] << ' ';
  cout << endl;

  for (int i = 1; i <= n; i++) cout << pos[i] << ' ';
  cout << endl;
  #endif

  while (q--) {

    int c, x, y;
    cin >> c >> x >> y;

    if (c == 0) {
      #ifdef LOCAL
      cout << "update " << x << ' ' << par[x] << ' ' << y << endl;
      #endif
      update(1, n, 0, pos[x], y);
    }

    else {
      int ans = 0;
      
      while (head[x] != head[y]) {
        if (weight[head[x]] > weight[head[y]]) swap(x, y);
        ans = max(ans, query(1, n, 0, pos[head[x]], pos[x]));
        #ifdef LOCAL
        cout << "query " << x << ' ' << head[x] << ' ' << pos[head[x]] << ' ' << pos[x] << endl;
        #endif
        x = par[head[x]];
      }

      if (weight[x] < weight[y]) swap(x, y);
      ans = max(ans, query(1, n, 0, pos[x], pos[y]));
      #ifdef LOCAL
      cout << "query " << x << ' ' << y << ' ' << pos[x] << ' ' << pos[y] << endl;
      #endif
      cout << ans << '\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();
}