Cod sursa(job #2307673)

Utilizator ApostolIlieDanielApostol Daniel ApostolIlieDaniel Data 25 decembrie 2018 13:35:35
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.3 kb
#include <bits/stdc++.h>

using namespace std;

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

const int MAXN = 1e5;

int s[MAXN + 1], dad[MAXN + 1], level[MAXN + 1], link[MAXN + 1], poz[MAXN + 1], v[MAXN + 1];

int seg[4 * MAXN + 1];

vector <int> gr[MAXN + 1];

int cnt;

int n;

int dfs (int nod, int tata) {
  s[nod] = 1;
  dad[nod] = tata;
  if (tata == -1)
    level[nod] = 1;
  else
    level[nod] = level[tata] + 1;

  for (auto fiu : gr[nod])
    if (fiu != tata)
      s[nod] += dfs (fiu, nod);

  return s[nod];
}

void make_links (int nod, int tata) {
  int mx;

  poz[nod] = ++cnt;
  mx = 0;

  for (auto fiu : gr[nod])
    if (fiu != tata && s[fiu] > s[mx])
      mx = fiu;

  if (mx) {
    link[mx] = link[nod];
    make_links (mx, nod);
  }

  for (auto fiu : gr[nod])
    if (fiu != tata && mx != fiu) {
      link[fiu] = fiu;
      make_links (fiu, nod);
    }
}

void update (int poz, int val) {
  poz += n;
  seg[poz] = val;
  poz = poz / 2;
  while (poz > 1) {
    seg[poz] = max (seg[2 * poz], seg[2 * poz + 1]);
    poz = poz / 2;
  }
}

int query (int st, int dr) {
  int sol = 0;
  st += n;
  dr += n + 1;
  while (st != dr) {
    if (st % 2)
      sol = max (sol, seg[st++]);
    if (dr % 2)
      sol = max (sol, seg[--dr]);
    st = st / 2;
    dr = dr / 2;
  }
  return sol;
}

int main() {
  int m, i, x, y, t, a, b, sol;

  fscanf (fin, "%d%d", &n, &m);

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

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

  dfs (1, -1);
  link[1] = 1;
  cnt = 0;
  make_links (1, -1);

  for (i = 1; i <= n; i++)
    update (poz[i], v[i]);

  while (m--) {
    fscanf (fin, "%d%d%d", &t, &a, &b);
    if (t == 0)
      update (poz[a], b);
    else {
      sol = 0;

      while (link[a] != link[b]) {
        if (level[link[a]] < level[link[b]])
          swap(a, b);
        sol = max (sol, query (poz[link[a]], poz[a]));
        a = dad[link[a]];
      }

      if (level[a] < level[b])
        swap (a, b);
      sol = max (sol, query (poz[b], poz[a]));

      fprintf (fout, "%d\n", sol);
    }
  }

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