Cod sursa(job #2689489)

Utilizator popashtefan10Popa Stefan popashtefan10 Data 21 decembrie 2020 07:53:16
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.53 kb
#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

const int NMAX = 100000;

int n, m, euler_idx, cnt_paths;
int val[NMAX + 5], euler[2 * NMAX + 5], first_ap[NMAX + 5], h[NMAX + 5];
int path_first[NMAX + 5], path[NMAX + 5], aint[8 * NMAX + 5];
vector<int> arb[NMAX + 5];

int dfs(int nod, int dad) {
  int max_fii = 0, nrfii = 1;
  h[nod] = h[dad] + 1;

  for(int i = 0; i < arb[nod].size(); i++)
    if(arb[nod][i] != dad) {
      int fii_vec = dfs(arb[nod][i], nod);
      nrfii += fii_vec;

      if(fii_vec > max_fii) {
        swap(arb[nod][0], arb[nod][i]);
        max_fii = fii_vec;
      }
    }

  return nrfii;
}

void euler_tour(int nod, int dad) {
  euler[++euler_idx] = nod;
  first_ap[nod] = euler_idx;
  for(int vec: arb[nod])
    if(vec != dad) {
      euler_tour(vec, nod);
      euler[++euler_idx] = nod;
    }
}

void path_decomposition() {
  for(int i = 1; i <= 2 * n - 1; i++) {
    if(h[euler[i]] - 1 != h[euler[i - 1]]) /// euler[i] face parte deja dintr-un lant
      continue;

    if(i == 1 || h[euler[i - 1]] - 1 != h[euler[i - 2]]) { /// euler[i] este tatal unui nou lant
      path[euler[i]] = ++cnt_paths;
      path_first[euler[i]] = euler[i];
    }
    else { /// sunt in interiorul unui lant
      path[euler[i]] = path[euler[i - 1]];
      path_first[euler[i]] = path_first[euler[i - 1]];
    }
  }
}

void init(int nod, int nst, int ndr) {
  if(nst == ndr)
    aint[nod] = euler[nst];
  else {
    int mij = (nst + ndr) / 2;
    init(2 * nod, nst, mij);
    init(2 * nod + 1, mij + 1, ndr);
    aint[nod] = (val[aint[2 * nod]] > val[aint[2 * nod + 1]]) ? aint[2 * nod] : aint[2 * nod + 1];
  }
}

void update(int nod, int nst, int ndr, int poz) {
  if(nst == ndr)
    return;
  int mij = (nst + ndr) / 2;
  if(poz <= mij) update(2 * nod, nst, mij, poz);
  else update(2 * nod + 1, mij + 1, ndr, poz);
  aint[nod] = (val[aint[2 * nod]] > val[aint[2 * nod + 1]]) ? aint[2 * nod] : aint[2 * nod + 1];
}

int query(int nod, int nst, int ndr, int qst, int qdr) {
  if(ndr < qst || nst > qdr) return 0;
  if(nst >= qst && ndr <= qdr) return val[aint[nod]];
  int mij = (nst + ndr) / 2;
  return max(query(2 * nod, nst, mij, qst, qdr), query(2 * nod + 1, mij + 1, ndr, qst, qdr));
}

int query(int nod1, int nod2) {
  int ans = 0;
  while(path[nod1] != path[nod2])
    if(h[path_first[nod1]] > h[path_first[nod2]]) {
      ans = max(ans, query(1, 1, 2 * n - 1, first_ap[path_first[nod1]], first_ap[nod1]));
      nod1 = euler[first_ap[euler[first_ap[path_first[nod1]] - 1]]];
    }
    else {
      ans = max(ans, query(1, 1, 2 * n - 1, first_ap[path_first[nod2]], first_ap[nod2]));
      nod2 = euler[first_ap[euler[first_ap[path_first[nod2]] - 1]]];
    }

  if(first_ap[nod1] > first_ap[nod2]) swap(nod1, nod2);
  ans = max(ans, query(1, 1, 2 * n - 1, first_ap[nod1], first_ap[nod2]));
  return ans;
}

int main() {
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);

  scanf("%d %d", &n, &m);
  for(int i = 1; i <= n; i++)
    scanf("%d", &val[i]);
  for(int i = 1; i < n; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    arb[x].push_back(y);
    arb[y].push_back(x);
  }

  dfs(1, 0);
  euler_tour(1, 0);
  path_decomposition();
  init(1, 1, 2 * n - 1);

  for(int i = 1; i <= m; i++) {
    int t, x, y;
    scanf("%d %d %d", &t, &x, &y);

    if(t == 0) {
      val[x] = y;
      update(1, 1, 2 * n - 1, first_ap[x]);
    }
    else
      printf("%d\n", query(x, y));
  }

  return 0;
}