Cod sursa(job #3168605)

Utilizator RolandPetreanPetrean Roland RolandPetrean Data 12 noiembrie 2023 20:01:25
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.83 kb
// https://www.infoarena.ro/problema/heavypath
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

const int N = 1e5;

int n, q;
vector<vector<int>> adj;
vector<int> val;

vector<int> parent, sz, depth, heavy_child;
void dfs(int v, int p) {
  parent[v] = p;
  depth[v] = depth[p] + 1;
  sz[v] = 1;

  int max_sz = 0;
  for (int u : adj[v]) {
    if (u == p) continue;

    dfs(u, v);
    sz[v] += sz[u];
    
    if (sz[u] > max_sz) {
      max_sz = sz[u];
      heavy_child[v] = u;
    }
  }
}

vector<int> heavy_head, heavy_order, where;
void decompose(int v, int head) {
  heavy_head[v] = head;
  where[v] = heavy_order.size();
  heavy_order.push_back(v);

  if (heavy_child[v]) decompose(heavy_child[v], head);
  for (int u : adj[v]) {
    if (u == parent[v] || u == heavy_child[v]) continue;
    decompose(u, u);
  }
}

vector<int> segtree;
void segtree_build(int v, int st, int dr) {
  if (st == dr) segtree[v] = val[heavy_order[st]];
  else {
    int mid = (st + dr) / 2;
    segtree_build(2 * v, st, mid);
    segtree_build(2 * v + 1, mid + 1, dr);
    segtree[v] = max(segtree[2 * v], segtree[2 * v + 1]);
  }
}
void segtree_update(int v, int st, int dr, int poz, int x) {
  if (st == dr) segtree[v] = x;
  else {
    int mid = (st + dr) / 2;
    if (poz <= mid) segtree_update(2 * v, st, mid, poz, x);
    else segtree_update(2 * v + 1, mid + 1, dr, poz, x);
    segtree[v] = max(segtree[2 * v], segtree[2 * v + 1]);
  }
}
int segtree_query(int v, int st, int dr, int l, int r) {
  if (st >= l && dr <= r) return segtree[v];
  int mid = (st + dr) / 2, res = 0;
  if (l <= mid) res = max(res, segtree_query(2 * v, st, mid, l, r));
  if (mid < r) res = max(res, segtree_query(2 * v + 1, mid + 1, dr, l, r));
  return res;
}

int heavy_query(int u, int v) {
  if (depth[u] > depth[v]) swap(u, v);
  if (heavy_head[u] == heavy_head[v]) {
    return segtree_query(1, 1, n, where[u], where[v]);
  }

  // if (depth[heavy_head[v]] < depth[heavy_head[u]]) swap(u, v);
  return max(
    segtree_query(1, 1, n, where[heavy_head[v]], where[v]),
    heavy_query(u, parent[heavy_head[v]])
  );
}

int main() {
  fin >> n >> q;

  val.assign(n + 1, 0);
  for (int i = 1; i <= n; ++i) fin >> val[i];

  adj.assign(n + 1, {});
  for (int i = 1; i <= n - 1; ++i) {
    int u, v;
    fin >> u >> v;

    adj[u].push_back(v);
    adj[v].push_back(u);
  }

  parent.assign(n + 1, 0);
  sz.assign(n + 1, 0);
  depth.assign(n + 1, 0);
  heavy_child.assign(n + 1, 0);
  dfs(1, 0);

  heavy_head.assign(n + 1, 0);
  heavy_order.assign(1, 0);
  where.assign(n + 1, 0);
  decompose(1, 1);

  segtree.assign(4 * (n + 1), 0);
  segtree_build(1, 1, n);

  while (q--) {
    int t, x, y;
    fin >> t >> x >> y;

    if (t == 0) {
      segtree_update(1, 1, n, where[x], y);
    } else {
      fout << heavy_query(x, y) << endl;
    }
  }
}