Cod sursa(job #2519883)

Utilizator AlexPop28Pop Alex-Nicolae AlexPop28 Data 8 ianuarie 2020 15:58:36
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.36 kb
#include <bits/stdc++.h>
#define dbg() cerr <<
#define name(x) (#x) << ": " << (x) << ' ' <<

using namespace std;

struct SegmTree {
  int n;
  vector<int> tree;
  SegmTree(const vector<int> &v) : n(v.size()), tree(2 * n) {
    for (int i = 0; i < n; ++i) {
      tree[i + n] = v[i];
    }
    for (int i = n - 1; i >= 1; --i) {
      tree[i] = max(tree[2 * i], tree[2 * i + 1]);
    }
  }
  void Update(int pos, int val) {
    for (tree[pos += n] = val; pos/= 2; ) {
      tree[pos] = max(tree[2 * pos], tree[2 * pos + 1]);
    }
  }
  int Query(int l, int r) {
    int ans = 0; ++r;
    for (l += n, r += n; l < r; l /= 2, r /= 2) {
      if (l & 1) ans = max(ans, tree[l++]);
      if (r & 1) ans = max(ans, tree[--r]);
    }
    return ans;
  }
};

void Precalc(int node, vector<int> &par, vector<int> &depth, vector<int> &sz, vector<vector<int>> &adj) {
  sz[node] = 1;
  for (int &x : adj[node]) {
    adj[x].erase(find(adj[x].begin(), adj[x].end(), node));
    par[x] = node;
    depth[x] = depth[node] + 1;
    Precalc(x, par, depth, sz, adj);
    sz[node] += sz[x];

    if (sz[x] > sz[adj[node][0]]) {
      swap(adj[node][0], x);
    }
  }
}

void DFS(int node, vector<int> &in, vector<int> &nxt, const vector<vector<int>> &adj) {
  static int timer = 0;
  in[node] = timer++;
  for (auto &x : adj[node]) {
    nxt[x] = x == adj[node][0] ? nxt[node] : x;
    DFS(x, in, nxt, adj);
  }
}

int main() {
  ifstream cin("heavypath.in");
  ofstream cout("heavypath.out");

  int n, m; cin >> n >> m;
  vector<int> val(n);
  for (int i = 0; i < n; ++i) {
    cin >> val[i];
  }
  vector<vector<int>> adj(n);
  for (int i = 0; i < n - 1; ++i) {
    int a, b; cin >> a >> b; --a, --b;
    adj[a].emplace_back(b);
    adj[b].emplace_back(a);
  }
  vector<int> par(n), depth(n), sz(n), in(n), nxt(n);
  Precalc(0, par, depth, sz, adj);
  DFS(0, in, nxt, adj);

  vector<int> v(n);
  for (int i = 0; i < n; ++i) {
    v[in[i]] = val[i];
  }
  
  SegmTree st(v);
  while (m--) {
    int t, x, y; cin >> t >> x >> y;
    if (t == 0) {
      st.Update(in[x - 1], y);
    } else {
      --x, --y;
      int ans = 0;
      while (nxt[x] != nxt[y]) {
        if (depth[nxt[x]] < depth[nxt[y]]) swap(x, y);
        ans = max(ans, st.Query(in[nxt[x]], in[x]));
        x = par[nxt[x]];
      }
      if (depth[x] < depth[y]) swap(x, y);
      ans = max(ans, st.Query(in[y], in[x]));

      cout << ans << '\n';
    }
  }
}