Cod sursa(job #2986757)

Utilizator mihaipriboimihailucapriboi mihaipriboi Data 1 martie 2023 02:04:12
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.85 kb
// Mihai Priboi

#include <stdio.h>
#include <vector>

using namespace std;

#define MAX_N 100'000

vector<int> graph[MAX_N];

int parent[MAX_N], depth[MAX_N], heavy[MAX_N], head[MAX_N], pos[MAX_N];
int aint[MAX_N * 2];
int v[MAX_N];

int n, current_pos;

int aint_get_max(int a, int b, int l, int r, int node) {
  if(l == a && r == b)
    return aint[node];

  int leftChild, rightChild, middle;
  middle = (r + l) / 2;
  leftChild = node + 1;
  rightChild = node + 2 * (middle - l + 1);

  int mx = 0;
  if(a <= middle)
    mx = max(mx, aint_get_max(a, min(middle, b), l, middle, leftChild));
  if(b > middle)
    mx = max(mx, aint_get_max(max(middle + 1, a), b, middle + 1, r, rightChild));

  return mx;
}

void aint_update(int l, int r, int node, int pos, int val) {
  if(l == r) {
    aint[node] = val;
    return;
  }

  int leftChild, rightChild, middle;
  middle = (r + l) / 2;
  leftChild = node + 1;
  rightChild = node + 2 * (middle - l + 1);

  if(pos <= middle)
    aint_update(l, middle, leftChild, pos, val);
  else
    aint_update(middle + 1, r, rightChild, pos, val);

  aint[node] = max(aint[leftChild], aint[rightChild]);
}

int dfs(int node) {
  int size = 1;
  int max_size = 0;
  heavy[node] = -1;

  for(int v : graph[node]) {
    if(v != parent[node]) {
      parent[v] = node;
      depth[v] = depth[node] + 1;

      int v_size = dfs(v);
      size += v_size;
      if(v_size > max_size) {
        max_size = v_size;
        heavy[node] = v;
      }
    }
  }
}

void decompose(int node, int h) {
  head[node] = h;
  pos[node] = current_pos++;

  if(heavy[node] != -1)
    decompose(heavy[node], h);
  
  for(int v : graph[node])
    if(v != parent[node] && v != heavy[node])
      decompose(v, v);
}

int query(int a, int b) {
  int res = 0;
  while(head[a] != head[b]) {
    if(depth[head[a]] > depth[head[b]])
      swap(a, b);

    res = max(res, aint_get_max(pos[head[b]], pos[b], 0, n - 1, 0));
    b = parent[head[b]];
  }
  
  if(depth[a] > depth[b])
    swap(a, b);

  res = max(res, aint_get_max(pos[a], pos[b], 0, n - 1, 0));
}

int main() {
  FILE *fin, *fout;
  int m, i, x, y, t;
  fin = fopen("heavypath.in", "r");
  fout = fopen("heavypath.out", "w");

  fscanf(fin, "%d%d", &n, &m);
  for(i = 0; i < n; i++)
    fscanf(fin, "%d", &v[i]);

  for(i = 0; i < n - 1; i++) {
    fscanf(fin, "%d%d", &x, &y);
    x--, y--;
    graph[x].push_back(y);
    graph[y].push_back(x);
  }

  dfs(0);
  current_pos = 0;
  decompose(0, 0);

  for(i = 0; i < n; i++)
    aint_update(0, n - 1, 0, pos[i], v[i]);

  for(i = 0; i < m; i++) {
    fscanf(fin, "%d%d%d", &t, &x, &y);

    if(t == 0)
      aint_update(0, n - 1, 0, pos[x - 1], y);
    else
      fprintf(fout, "%d\n", query(x - 1, y - 1));
  }

  fclose(fin);
  fclose(fout);
  return 0;
}