Cod sursa(job #1505015)

Utilizator juniorOvidiu Rosca junior Data 18 octombrie 2015 17:31:57
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.48 kb


#include <cstdio>
#include <algorithm>
#include <vector>
#include <fstream>

using namespace std;

#define MAXN 100010

int n, m, nL;
int a[MAXN], niv[MAXN], g[MAXN], l[MAXN], aint[4 * MAXN];
bool v[MAXN];
int lTata[MAXN], lNiv[MAXN], lDim[MAXN], lPoz[MAXN];
vector<int> G[MAXN], P[MAXN];
ifstream fin ("heavypath.in");


void read_graph() {
  int i, x, y;
  fin >> n >> m;
  for (i = 1; i <= n; i++)
    fin >> a[i];
  for (i = 1; i < n; i++) {
    fin >> x >> y;
    G[x].push_back(y);
    G[y].push_back(x);
  }
}

void df(int nod) {
  int hN = -1; 
  bool frunza = true;
  vector<int>::iterator it;
  v[nod] = true; g[nod] = 1; 
  for (it = G[nod].begin(); it != G[nod].end(); it++) { 
    if (not v[*it]) { 
      frunza = false; 
      niv[*it] = niv[nod] + 1; 
      df(*it); 
      g[nod] += g[*it]; 
      if(hN == -1) 
        hN = *it;
      else
        if(g[hN] < g[*it])
          hN = *it; 
    }
  }
  if (frunza) { 
    l[nod] = ++nL; 
    lDim[nL] = 1; 
    P[nL].push_back(nod); 
    return;
  }
  l[nod] = l[hN]; 
  lDim[l[nod]]++; 
  P[l[nod]].push_back(nod); 
  for (it = G[nod].begin(); it != G[nod].end(); it++) {
    if (*it != hN /*and v[*it] /*niv[*it] >= niv[nod]*/) {
      lTata[l[*it]] = nod; 
      lNiv[l[*it]] = niv[nod];
    }
  }
}

void build(int nod, int left, int right, int decalaj, int lant) {
  if(left == right) {
    aint[nod + decalaj] = a[P[lant][left - 1]];
    return;
  }
  int med = (left + right) / 2;
  build(nod * 2, left, med, decalaj, lant);
  build(nod * 2 + 1, med + 1, right, decalaj, lant);
  aint[nod + decalaj] = max(aint[nod * 2 + decalaj], aint[nod * 2 + 1 + decalaj]);
}

void make_paths() {
  niv[1] = 1;
  df(1);
  for(int i = 1; i <= nL; ++i) {
    reverse(P[i].begin(), P[i].end());
    if (i > 1)
      lPoz[i] = lPoz[i - 1] + lDim[i - 1] * 4;
    build(1, 1, lDim[i], lPoz[i], i);
  }
}

void update(int nod, int left, int right, int poz, int val, int decalaj) {
  if(left == right) {
    aint[nod + decalaj] = val;
    return;
  }
  int med = (left + right) / 2;
  if(poz <= med)
    update(nod * 2, left, med, poz, val, decalaj);
  else
    update(nod * 2 + 1, med + 1, right, poz, val, decalaj);
  aint[nod + decalaj] = max(aint[nod * 2 + decalaj], aint[nod * 2 + 1 + decalaj]);
}

int query(int nod, int left, int right, int qleft, int qright, int decalaj) {
  if(qleft <= left && right <= qright)
    return aint[nod + decalaj];
  int med = (left + right) / 2, rez = 0;
  if(qleft <= med)
    rez = max(rez, query(nod * 2, left, med, qleft, qright, decalaj));
  if(med < qright)
    rez = max(rez, query(nod * 2 + 1, med + 1, right, qleft, qright, decalaj));
  return rez;
}

void solve() {
  int t, x, y, sol = 0;
  for (int i = 1; i <= m; ++i) {
    fin >> t >> x >> y;
    if (t == 0)
      update(1, 1, lDim[l[x]], niv[x] - lNiv[l[x]], y, lPoz[l[x]]);
    else {
      sol = 0;
      while (1) {
        if (l[x] == l[y]) {
          if (niv[x] > niv[y])
            swap(x, y);
          sol = max(sol, query(1, 1, lDim[l[x]], niv[x] - lNiv[l[x]], niv[y] - lNiv[l[x]], lPoz[l[x]]));
          break;
        }
        if (lNiv[l[x]] < lNiv[l[y]])
          swap(x, y);
        sol = max(sol, query(1, 1, lDim[l[x]], 1, niv[x] - lNiv[l[x]], lPoz[l[x]]));
        x = lTata[l[x]];
      }
      printf("%d\n", sol);
    }
  }
}

int main() {
  freopen("heavypath.out", "w", stdout);
  
  read_graph();
  make_paths();
  solve();
  return 0;
}