Cod sursa(job #2193414)

Utilizator retrogradLucian Bicsi retrograd Data 10 aprilie 2018 00:23:41
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.96 kb
#include <bits/stdc++.h>
 
using namespace std;
 
struct HeavyLight {
    vector<vector<int>> G;
    vector<int> jump, sub, depth, lin, parent;
  
  HeavyLight(int n) : G(n), jump(n), sub(n), 
    depth(n), lin(n), parent(n) {}
  
  void AddEdge(int a, int b) {
    G[a].push_back(b);
    G[b].push_back(a);
  }
  
  void Build() { dfs_sub(0, -1, 0); dfs_jump(0, 0); }
  
  // Gets the position in the HL linearization
  int GetPosition(int node) { return lin[node]; }
  
  // Gets an array of ranges of form [li...ri)
  // that correspond to the ranges you would need
  // to query in the underlying structure
  vector<pair<int, int>> GetPathRanges(int a, int b) {
    vector<pair<int, int>> ret;
    while (jump[a] != jump[b]) {
      if (depth[jump[a]] < depth[jump[b]])
        swap(a, b);
      
      ret.emplace_back(lin[jump[a]], lin[a] + 1);
      a = parent[jump[a]];
    }
    if (depth[a] < depth[b]) swap(a, b);
    ret.emplace_back(lin[b], lin[a] + 1);
    return ret;
  }
  
  int dfs_sub(int node, int par, int dep) {
    sub[node] = 1; parent[node] = par; depth[node] = dep;
    if (par != -1) {
        G[node].erase(find(G[node].begin(), G[node].end(), par));
    }
    for (auto vec : G[node])
        sub[node] += dfs_sub(vec, node, dep + 1);
    return sub[node];
  }
  
  int timer = 0;
  void dfs_jump(int node, int jmp) {
    jump[node] = jmp; lin[node] = timer++;
    if (G[node].empty()) return;

    pair<int, int> best{-1, -1};
    for (auto vec : G[node])
        best = max(best, {sub[vec], vec});
    dfs_jump(best.second, jmp);
    for (auto vec : G[node]) if (vec != best.second)
      dfs_jump(vec, vec);
  }
};
 
class SegmTree {
    vector<int> T;
    int n;
 
public:
 
    SegmTree(int n) : T(4 * n), n(n) {}
 
    void Update(int pos, int val) {
        for (T[pos += n] = val; pos > 1; pos /= 2)
            T[pos / 2] = max(T[pos], T[pos ^ 1]);
    }
 
    int Query(int b, int e) {
        int res = 0;
        for (b += n, e += n; b < e; b /= 2, e /= 2) {
            if (b % 2) res = max(res, T[b++]);
            if (e % 2) res = max(res, T[--e]);
        }
        return res;
    }
};
 
int main() {
    ifstream fin("heavypath.in");
    ofstream fout("heavypath.out");
 
    int n, m; fin >> n >> m;
 
    SegmTree st(n);
    HeavyLight hl(n);
 
    vector<int> vals(n);
    for (int i = 0; i < n; ++i) {
        fin >> vals[i];
    }
 
    for (int i = 1; i < n; ++i) {
        int a, b; fin >> a >> b;
        hl.AddEdge(a - 1, b - 1);
    }
 
    hl.Build();
 
 
    for (int i = 0; i < n; ++i)
        st.Update(hl.GetPosition(i), vals[i]);
 
    while (m--) {
        int t, a, b;
        fin >> t >> a >> b;
 
        if (t == 0) {
            st.Update(hl.GetPosition(a - 1), b);
        } else {
            int ans = 0;
 
            for (auto p : hl.GetPathRanges(a - 1, b - 1)) {
                assert(p.first < p.second);
                ans = max(ans, st.Query(p.first, p.second));
            }
            fout << ans << '\n';
        }
    }
 
    return 0;
}