Cod sursa(job #2950925)

Utilizator GabiTulbaGabi Tulba-Lecu GabiTulba Data 4 decembrie 2022 20:50:10
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.09 kb
#include <bits/stdc++.h>
#include <climits>

#define MAX_LOG 17
#define MAX_N 100005

using namespace std;

FILE *fin, *fout;
int N, M, global_idx = 1, global_path_idx = 1, Val, Pos, S, E;
vector<int> G[MAX_N];
int T[4 * MAX_N];
int dp[MAX_LOG][MAX_N];
int s[MAX_N], cost[MAX_N], depth[MAX_N], path_start[MAX_N];
struct node_info {
  int idx, path_idx;
} info[MAX_N];

void update(int node, int start, int end) {
  if(start == end) {
    T[node] = Val;
  } else {
    int mid = (start + end) / 2;
    if(Pos <= mid)
      update(2 * node, start, mid);
    else
      update(2 * node + 1, mid + 1, end);
    T[node] = max(T[2 * node], T[2 * node + 1]);
  }
}

void query(int node, int start, int end) {
  if(S <= start && end <= E) {
    Val = max(Val, T[node]);
  } else {
    int mid = (start + end) / 2;
    if(S <= mid)
      query(2 * node, start, mid);
    if(E > mid)
      query(2 * node + 1, mid + 1, end);
  }
}

void precalc_hpd(int node) {
  Pos = global_idx;
  Val = cost[node];
  info[node].idx = global_idx;
  info[node].path_idx = global_path_idx;
  update(1, 1, N);

  int best = 0;
  for(auto &son: G[node]) {
    if(dp[0][node] != son && (best == 0 || s[best] < s[son]))
      best = son;
  }

  if(best == 0) {
    return;
  }

  global_idx++;
  precalc_hpd(best);

  for(auto &son: G[node]) {
    if(son != dp[0][node] && son != best) {
      global_idx++;
      path_start[++global_path_idx] = son;
      precalc_hpd(son);
    }
  }
}

void hpd_update(int node, int value) {
  Pos = info[node].idx;
  Val = value;
  update(1, 1, N);
}

int hpd_query(int father, int son) {
  Val = INT_MIN;
  while(info[father].path_idx != info[son].path_idx) {
    S = info[path_start[info[son].path_idx]].idx;
    E = info[son].idx;
    query(1, 1, N);
    son = dp[0][path_start[info[son].path_idx]];
  }
  S = info[father].idx;
  E = info[son].idx;
  query(1, 1, N);

  return Val;
}

int precalc_lca(int node, int father, int d) {
  dp[0][node] = father;
  depth[node] = d;
  s[node] = 1;

  for(int i = 1; i < MAX_LOG; i++)
      dp[i][node] = dp[i-1][dp[i - 1][node]];

  for(auto &son: G[node])
    if(depth[son] == 0)
      s[node] += precalc_lca(son, node, d + 1);

  return s[node];
}

int lca(int x, int y) {
  if(depth[x] > depth[y])
    swap(x, y);

  for(int i = MAX_LOG - 1; i >= 0; i--)
    if(depth[dp[i][y]] >= depth[x])
      y = dp[i][y];

  if(x == y)
    return x;

  for (int i = MAX_LOG - 1; i >= 0; i--) {
    if(dp[i][y] != dp[i][x]) {
      y = dp[i][y];
      x = dp[i][x];
    }
  }

  return dp[0][x];
}
int main() {
  fin = fopen("heavypath.in", "r");
  fout = fopen("heavypath.out", "w");

  fscanf(fin, "%d%d", &N, &M);

  for(int i = 1; i<= N; i++)
    fscanf(fin, "%d", &cost[i]);

  for(int i = 1; i < N; i++) {
    int x, y;
    fscanf(fin, "%d%d", &x, &y);
    G[x].push_back(y);
    G[y].push_back(x);
  }

  precalc_lca(1, 1, 1);
  path_start[1] = 1;
  precalc_hpd(1);

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

    if(t == 0) {
      hpd_update(x, y);
    } else {
      z = lca(x, y);


      fprintf(fout, "%d\n", max(hpd_query(z, x), hpd_query(z, y)));
    }
  }
}