Cod sursa(job #2907677)

Utilizator avtobusAvtobus avtobus Data 31 mai 2022 08:22:23
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.42 kb
#include <stdio.h>
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;
int SZ;
vector<int> st;
void build() {
  for(int x = SZ-1; x; --x) {
    st[x] = max(st[2*x], st[2*x+1]);
  }
}
void set_val(int x, int val) {
  for(st[x += SZ] = val; x; x /= 2) {
    st[x/2] = max(st[x], st[x^1]);
  }
}
int query(int l, int r) {
  int res = 0;
  for(l += SZ, r+= SZ; l < r; l /= 2, r /= 2) {
    if (l&1) { res = max(res, st[l]); l++; }
    if (r&1) { --r; res = max(res, st[r]); }
  }
  return res;
}
int main(void) {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);
  int N, M;
  cin >> N >> M;
  vector<int> A(N);
  for(auto &a: A) { cin >> a; }
  SZ = 1; while(SZ < N) SZ *= 2;
  st.resize(2*SZ, 0);
  int edge_cnt = 0;
  vector<int> nxt(2*N), head(N), ende(2*N);
  auto add_edge = [&](int u, int v){
    edge_cnt++;
    nxt[edge_cnt] = head[u];
    head[u] = edge_cnt;
    ende[edge_cnt] = v;
  };
  for(int i = 1; i < N; i++) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    add_edge(u, v);
    add_edge(v, u);
  }
  vector<int> depth(N), par(N, -1), heavy(N,-1);
  auto dfs = [&](auto self, int nod, int src)->int {
    int sz = 1, max_subtree = 0;
    for(int e = head[nod]; e; e = nxt[e]) {
      int nbr = ende[e];
      if (nbr == src) continue;
      par[nbr] = nod;
      depth[nbr] = depth[nod] + 1;
      int subtree_sz = self(self, nbr, nod);
      if (subtree_sz > max_subtree) {
        max_subtree = subtree_sz;
        heavy[nod] = nbr;
      }
      sz += subtree_sz;
    }
    return sz;
  };
  dfs(dfs, 0, -1);
  vector<int> treePos(N), root(N);
  for(int nod = 0, currentPos = 0; nod < N; ++nod) {
    if (par[nod] == -1 || heavy[par[nod]] != nod) { // start new heavy path at nod;
      for(int ch = nod; ch != -1; ch = heavy[ch]) {
        root[ch] = nod;
        treePos[ch] = currentPos++;
      }
    }
  }
  auto dbg = [&]() {
    cout << std::left << setw(12) << "depth:";
    for(int i = 0; i < N; i++) { cout << depth[i] << " "; } cout << endl;
    cout << setw(12) << "parent:";
    for(int i = 0; i < N; i++) { cout << par[i] + 1 << " "; } cout << endl;
    cout << setw(12) << "heavy:";
    for(int i = 0; i < N; i++) { cout << heavy[i] + 1 << " "; } cout << endl;
    cout << setw(12) << "treePos:";
    for(int i = 0; i < N; i++) { cout << treePos[i] << " "; } cout << endl;
    cout << setw(12) << "root:";
    for(int i = 0; i < N; i++) { cout << root[i] + 1 << " "; } cout << endl;
  };
  // dbg();
  for(int i = 0; i < N; ++i) {
    st[treePos[i] + SZ] = A[i];
  }
  build();
  auto dbg2 = [&](){
    cout << string(60,'-') << endl;
    cout << std::left << setw(12) << "segtree:";
    for(int i = 1; i < (int)st.size(); i++) { cout << st[i] << ' '; } cout << endl;
  };
  // dbg2();
  for(int mm = 1; mm <= M; mm++) {
    int q, a,b;
    cin >> q >> a >> b;
    if (q == 0) {
      --a;
      set_val(treePos[a], b);
      // dbg2();
    } else {
      --a, --b;
      int res = 0;
      for(; root[a] != root[b]; b = par[root[b]]) {
        if (depth[root[a]] > depth[root[b]]) swap(a,b);
        res = max(res, query(treePos[root[b]], treePos[b]+1));
      }
      if (depth[a] > depth[b]) swap(a,b);
      res = max(res, query(treePos[a], treePos[b]+1));
      // cout << setw(10) << "ANS:";
      cout << res << "\n";
    }
  }

  return 0;
}