Cod sursa(job #3364578)

Utilizator freak93Adrian Budau freak93 Data 5 septembrie 2026 22:28:27
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.02 kb
#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>

using namespace std;

struct SegmentTree {
  SegmentTree(int size) : size(size), data(size * 2, 0) {}

  void update(int pos, int value) {
    for (data[pos += size] = value; pos; pos /= 2)
      data[pos / 2] = max(data[pos], data[pos ^ 1]);
  }

  int query(int l, int r) {
    int answer = 0;
    for (l += size, r += size; l < r; l /= 2, r /= 2) {
      if (l % 2)
        answer = max(answer, data[l++]);
      if (r % 2)
        answer = max(answer, data[--r]);
    }
    return answer;
  }

  int size;
  vector<int> data;
};

struct HLD {
  HLD(int size)
      : value(size), edges(size), time(size), start(size), link(size),
        segment_tree(size) {}

  int size() const { return edges.size(); }

  void add_edge(int x, int y) {
    edges[x].push_back(y);
    edges[y].push_back(x);
  }

  void prepare() {
    dfs_size(0);
    dfs_time(0, 0, 0);
    for (int i = 0; i < size(); ++i)
      segment_tree.update(time[i], value[i]);
  }

  // returns subtree size
  int dfs_size(int node, int parent = -1) {
    auto p = find(edges[node].begin(), edges[node].end(), parent);
    if (p != edges[node].end())
      edges[node].erase(p);

    int max_size = 0;
    int total = 1;
    for (auto it = edges[node].begin(); it != edges[node].end(); ++it) {
      int sub = dfs_size(*it, node);
      if (sub > max_size) {
        iter_swap(it, edges[node].begin());
        max_size = sub;
      }

      total += sub;
    }
    return total;
  }

  // returns next available slot
  int dfs_time(int node, int pos, int chain_start) {
    time[node] = pos;
    start[node] = chain_start;
    if (edges[node].empty())
      return pos + 1;

    link[edges[node][0]] = link[node];
    int next = dfs_time(edges[node][0], pos + 1, chain_start);

    for (auto it = edges[node].begin() + 1; it != edges[node].end(); ++it) {
      link[*it] = node;
      next = dfs_time(*it, next, next);
    }
    return next;
  }

  void update(int node, int value) { segment_tree.update(time[node], value); }

  int query(int x, int y) {
    int answer = 0;
    while (start[x] != start[y]) {
      if (start[x] < start[y])
        swap(x, y);
      answer = max(answer, segment_tree.query(start[x], time[x] + 1));
      x = link[x];
    }

    if (time[x] > time[y])
      swap(x, y);
    answer = max(answer, segment_tree.query(time[x], time[y] + 1));
    return answer;
  }

  vector<int> value;
  vector<vector<int>> edges;

  vector<int> time;
  vector<int> start;
  vector<int> link;

  SegmentTree segment_tree;
};

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

  int N, M;
  cin >> N >> M;
  HLD graph(N);
  for (int i = 0; i < N; ++i)
    cin >> graph.value[i];

  for (int i = 1; i < N; ++i) {
    int x, y;
    cin >> x >> y;
    graph.add_edge(x - 1, y - 1);
  }

  graph.prepare();

  for (int i = 0; i < M; ++i) {
    int type, x, y;
    cin >> type >> x >> y;
    if (type == 0)
      graph.update(x - 1, y);
    else {
      cout << graph.query(x - 1, y - 1) << "\n";
    }
  }
}