Cod sursa(job #2459012)

Utilizator mihai50000Mihai-Cristian Popescu mihai50000 Data 22 septembrie 2019 09:37:03
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.53 kb
#include <bits/stdc++.h>
using namespace std;

class InputReader
{
private:

  static const int SIZE = 1 << 12;
  char buf[SIZE]; int ptx;

  FILE *inFile;

  inline void advance (void)
  {
    if (++ptx == SIZE) {
      ptx = 0; fread(buf, SIZE, 1, inFile); }
  }

  inline char current (void)
  {
    return buf[ptx];
  }

public:

  InputReader (const char *fileName)
  {
    inFile = fopen(fileName, "r"); ptx = 0;
    fread(buf, SIZE, 1, inFile);
  }

  InputReader &operator >> (int &val)
  {
    val = 0;
    while (current() < '0' || current() > '9') {
      advance(); }
    while (current() >= '0' && current() <= '9') {
      val = val * 10 + (current() - '0');
      advance(); }
    return *this;
  }
} in("heavypath.in");
ofstream out("heavypath.out");

const int DIM = 100005;

int szt[DIM], lev[DIM], wch[DIM], ftc[DIM], val[DIM];
int ord[DIM], fis[DIM], pos[DIM], sgt[DIM << 2];

vector<int> edg[DIM];

void dfs1 (int x, int f = 0)
{
  static int nr = 0; int mx = -1;
  szt[x] = 1; lev[x] = lev[f] + 1;
  if (f) {
    edg[x].erase(find(edg[x].begin(), edg[x].end(), f)); }
  for (int y : edg[x]) {
    dfs1(y, x); szt[x] += szt[y];
    mx = max(mx, szt[y]); }
  for (int it = 0; it < edg[x].size(); ++it) {
    int y = edg[x][it];
    if (szt[y] == mx) {
      swap(edg[x][0], edg[x][it]); break; } }
  if (mx == -1) {
    wch[x] = ++nr; }
  else {
    wch[x] = wch[edg[x][0]];
    for (int y : edg[x]) {
      if (wch[y] != wch[x]) {
        ftc[wch[y]] = x; } } }
}

void dfs2 (int x)
{
  static int nr = 0;
  ord[++nr] = x; pos[x] = nr;
  for (int y : edg[x]) {
    dfs2(y); }
}

void build (int nd, int le, int ri)
{
  if (le == ri) {
    sgt[nd] = val[ord[le]]; }
  else {
    int md = (le + ri) >> 1;
    build(nd << 1, le, md);
    build(nd << 1 | 1, md + 1, ri);
    sgt[nd] = max(sgt[nd << 1], sgt[nd << 1 | 1]); }
}

void update (int nd, int le, int ri, int ps, int vl)
{
  if (le == ri) {
    sgt[nd] = vl; }
  else {
    int md = (le + ri) >> 1;
    if (ps <= md) {
      update(nd << 1, le, md, ps, vl); }
    else {
      update(nd << 1 | 1, md + 1, ri, ps, vl); }
    sgt[nd] = max(sgt[nd << 1], sgt[nd << 1 | 1]); }
}

int query (int nd, int le, int ri, int st, int en)
{
  if (st == le && en == ri) {
    return sgt[nd]; }
  else {
    int md = (le + ri) >> 1;
    if (en <= md) {
      return query(nd << 1, le, md, st, en); }
    else if (md < st) {
      return query(nd << 1 | 1, md + 1, ri, st, en); }
    else {
      return max(query(nd << 1, le, md, st, md),
                 query(nd << 1 | 1, md + 1, ri, md + 1, en)); } }
}

int query_heavy (int x, int y, int n)
{
  if (wch[x] == wch[y]) {
    if (pos[x] > pos[y]) {
      swap(x, y); }
    return query(1, 1, n, pos[x], pos[y]); }
  else {
    if (lev[ftc[wch[x]]] > lev[ftc[wch[y]]]) {
      swap(x, y); }
    return max(query(1, 1, n, fis[wch[y]], pos[y]),
               query_heavy(x, ftc[wch[y]], n)); }
}

int main (void)
{
  int n, q; in >> n >> q;
  for (int i = 1; i <= n; ++i) {
    in >> val[i]; }
  for (int i = 1; i < n; ++i) {
    int x, y; in >> x >> y;
    edg[x].push_back(y);
    edg[y].push_back(x); }
  dfs1(1); dfs2(1);
  for (int i = 1; i <= n; ++i) {
    int x = ord[i - 1], y = ord[i];
    if (wch[x] != wch[y]) {
      fis[wch[y]] = i; } }
  build(1, 1, n);
  while (q--) {
    int t, x, y; in >> t >> x >> y;
    if (t == 0) {
      update(1, 1, n, pos[x], y); }
    else {
      out << query_heavy(x, y, n) << "\n"; } }
  return 0;
}