Cod sursa(job #2986764)

Utilizator YusyBossFares Yusuf YusyBoss Data 1 martie 2023 08:39:31
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.82 kb
#include <bits/stdc++.h>
#define NMAX 100000

using namespace std;

int n;
int v[NMAX + 1];
int vtata[NMAX + 1];
int vlevel[NMAX + 1];
int vdown[NMAX + 1];
vector <int> vsons[NMAX + 1];
int vtopchain[NMAX + 1];
int vindexaint[NMAX + 1];
int vorderaint[NMAX + 1];
int crtindex;

struct straint {
  int vaint[4 * NMAX + 1];

  void init() {
    int i;
    for (i = 0; i <= 4 * NMAX; i++)
      vaint[i] = 0;
  }

  void build(int node, int left, int right) {
    if (left == right) {
      vaint[node] = v[vorderaint[left]];
      return;
    }

    int med = (left + right) / 2;
    build(node * 2, left, med);
    build(node * 2 + 1, med + 1, right);

    vaint[node] = max(vaint[node * 2], vaint[node * 2 + 1]);
  }

  void update(int node, int left, int right, int poz, int val) {
    if (left == right) {
      vaint[node] = val;
      return;
    }

    int med = (left + right) / 2;
    if (poz <= med)
      update(node * 2, left, med, poz, val);
    else
      update(node * 2 + 1, med + 1, right, poz, val);

    vaint[node] = max(vaint[node * 2], vaint[node * 2 + 1]);
  }

  int query(int node, int left, int right, int qleft, int qright) {
    if (left == qleft && right == qright)
      return vaint[node];

    int med = (left + right) / 2;
    if (qleft <= med && qright > med)
      return max(query(node * 2, left, med, qleft, med), query(node * 2 + 1, med + 1, right, med + 1, qright));
    else if (qleft <= med)
      return query(node * 2, left, med, qleft, qright);
    else
      return query(node * 2 + 1, med + 1, right, qleft, qright);
  }
};

straint AINT;

void dfs1(int node, int tata, int level) {
  int i, nsons;

  vtata[node] = tata;
  vdown[node] = 1;
  vlevel[node] = level;

  nsons = vsons[node].size();
  for (i = 0; i < nsons; i++) {
    int newnode = vsons[node][i];
    if (newnode != tata) {
      dfs1(newnode, node, level + 1);
      vdown[node] += vdown[newnode];
    }
  }
}

void dfs2(int node, int tata, int chainTop) {
  int i, nsons, heavyIndex, maxDown;

  vtopchain[node] = chainTop;
  vindexaint[node] = crtindex;
  vorderaint[crtindex] = node;
  crtindex++;

  maxDown = 0;
  heavyIndex = -1;
  nsons = vsons[node].size();
  for (i = 0; i < nsons; i++) {
    int newnode = vsons[node][i];
    if (newnode != tata) {
      if (vdown[node] > maxDown) {
        heavyIndex = i;
        maxDown = vdown[node];
      }
    }
  }

  if (heavyIndex != -1)
    dfs2(vsons[node][heavyIndex], node, chainTop);

  for (i = 0; i < nsons; i++) {
    int newnode = vsons[node][i];
    if (newnode != tata && i != heavyIndex)
      dfs2(newnode, node, newnode);
  }

}

int query(int node1, int node2) {
  int sol = 0;
  while (vtopchain[node1] != vtopchain[node2]) {
    if (vlevel[vtopchain[node2]] > vlevel[vtopchain[node1]])
      swap(node1, node2);

    sol = max(sol, AINT.query(1, 0, n - 1, vindexaint[vtopchain[node1]], vindexaint[node1]));
    node1 = vtata[vtopchain[node1]];
  }

  sol = max(sol, AINT.query(1, 0, n - 1, min(vindexaint[node1], vindexaint[node2]), max(vindexaint[node1], vindexaint[node2])));
  return sol;
}

void update(int node, int val) {
  AINT.update(1, 0, n - 1, vindexaint[node], val);
}

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

  int i, q, op, x, y;
  fscanf(fin, "%d%d", &n, &q);

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

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

  dfs1(1, 0, 1);
  crtindex = 0;
  dfs2(1, 0, 1);
  AINT.build(1, 0, n - 1);

  while (q--) {
    fscanf(fin, "%d%d%d", &op, &x, &y);

    if (op == 0)
      update(x, y);
    else
      fprintf(fout, "%d\n", query(x, y));
  }
  return 0;
}