Cod sursa(job #2271254)

Utilizator stefan_creastaStefan Creasta stefan_creasta Data 28 octombrie 2018 12:11:18
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.95 kb
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int NMAX = 100005;
const int INF = 0x7fffffff;
int valNod[NMAX];
int hNod[NMAX];
int size[NMAX];
int heavy[NMAX];
int father[NMAX];
int aint[4 * NMAX];
int position[NMAX];
bool visited[NMAX];
int chainHead[NMAX];
vector <int> g[NMAX];
vector <int> heavyTransversal;

int n, m;

void dfsSize(int u) {
  visited[u] = 1;
  size[u] = 1;
  for(auto v : g[u]) {
    if(!visited[v]) {
      father[v] = u;
      dfsSize(v);
      size[u] += size[v];
      if(size[v] > size[heavy[u]]) {
        heavy[u] = v;
      }
    }
  }
}
void dfsHeavy(int u, int h, int head) {
  visited[u] = 1;
  hNod[u] = h;
  chainHead[u] = head;
  position[u] = (int)heavyTransversal.size();
  heavyTransversal.push_back(valNod[u]);
  if(heavy[u] != 0) {
    dfsHeavy(heavy[u], h + 1, head);
    for(auto v : g[u]) {
      if(!visited[v]) {
        dfsHeavy(v, h + 1, v);
      }
    }
  }
}
void update(int nod, int st, int dr, int i, int val) {
  if(st == dr) {
    aint[nod] = val;
  }
  else {
    int mij = (st + dr) / 2;
    if(i <= mij) {
      update(2 * nod, st, mij, i, val);
    }
    else {
      update(2 * nod + 1, mij + 1, dr, i, val);
    }
    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
  }
}
int query(int nod, int st, int dr, int x, int y) {
  if(x <= st && dr <= y) {
    return aint[nod];
  }
  else {
    int sol = -INF, mij = (st + dr) / 2;
    if(x <= mij) {
      sol = max(sol, query(2 * nod, st, mij, x, y));
    }
    if(mij + 1 <= y) {
      sol = max(sol, query(2 * nod + 1, mij + 1, dr, x, y));
    }
    return sol;
  }
}
void update(int i, int val) {
  update(1, 1, n, i, val);
}
int query(int x, int y) {
  return query(1, 1, n, x, y);
}
int maxPath(int u, int v) {
  if(chainHead[u] == chainHead[v]) {
    if(position[u] < position[v]) {
      return query(position[u], position[v]);
    }
    else {
      return query(position[v], position[u]);
    }
  }
  else if(hNod[chainHead[u]] > hNod[chainHead[v]]) {
    return max(maxPath(father[chainHead[u]], v), query(position[chainHead[u]], position[u]));
  }
  else {
    return max(maxPath(u, father[chainHead[v]]), query(position[chainHead[v]], position[v]));
  }
}

int main() {
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);
  scanf("%d%d", &n, &m);
  size[0] = 0;
  for(int i = 1; i <= n; i++) {
    scanf("%d", &valNod[i]);
    visited[i] = 0;
    heavy[i] = 0;
  }
  for(int i = 1; i < n; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    g[x].push_back(y);
    g[y].push_back(x);
  }
  heavyTransversal.push_back(0);
  dfsSize(1);
  for(int i = 1; i <= n; i++) {
    visited[i] = 0;
  }
  father[1] = 0;
  hNod[0] = 0;
  dfsHeavy(1, 1, 1);
  for(int i = 1; i <= n; i++) {
    update(i, heavyTransversal[i]);
  }
  for(int i = 1; i <= m; i++) {
    int t, x, y;
    scanf("%d%d%d", &t, &x, &y);
    if(t == 0) {
      update(position[x], y);
    }
    else if(t == 1) {
      printf("%d\n", maxPath(x, y));
    }
  }
  return 0;
}