Cod sursa(job #2272364)

Utilizator vladisimovlad coneschi vladisimo Data 30 octombrie 2018 08:52:13
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.33 kb
#include <algorithm>
#include <cstdio>
#include <vector>

const int MAX_N = 100000;

std::vector<int> neighbours[1 + MAX_N];
std::vector<int> heavyTraversal;

int position[1 + MAX_N], Size[1 + MAX_N], heavySon[1 + MAX_N], chainId[1 + MAX_N], chainCount;
int val[1 + MAX_N], ArbInt[4 * MAX_N], N;

bool visited[1 + MAX_N];

struct Chain {
  int head;
  int master;
  int headDepth;
};

Chain chains[MAX_N];


void update(int nod, int st, int dr, int i, int val) {
  if (st == dr) {
    ArbInt[nod] = val;
  } else {
    int mid = (st + dr) / 2;
    if (i <= mid)
      update(2 * nod, st, mid, i, val);
    else
      update(2 * nod + 1, mid + 1, dr, i, val);
    ArbInt[nod] = std::max(ArbInt[2 * nod], ArbInt[2 * nod + 1]);
  }
}

void update(int i, int val) {
  update(1, 1, N, i, val);
}

int query(int nod, int st, int dr, int begin, int end) {
  if (begin <= st && dr <= end)
    return ArbInt[nod];
  int mid = (st + dr) / 2;
  int sol = 0;
  if (begin <= mid)
    sol = std::max(sol, query(2 * nod, st, mid, begin, end));
  if (mid < end)
    sol = std::max(sol, query(2 * nod + 1, mid + 1, dr, begin, end));
  return sol;
}

int query(int begin, int end) {
  return query(1, 1, N, begin, end);
}

void dfsSize(int u) {
  visited[u] = true;
  Size[u] = 1;
  for (int v : neighbours[u]) {
    if (!visited[v]) {
      dfsSize(v);
      Size[u] += Size[v];
      if (Size[heavySon[u]] < Size[v])
        heavySon[u] = v;
    }
  }
}

void dfsHeavy(int u, int depthU) {
  visited[u] = true;
  heavyTraversal.push_back(val[u]);
  position[u] = heavyTraversal.size();
  chainId[u] = chainCount;
  if (heavySon[u] != 0) {
    dfsHeavy(heavySon[u], depthU + 1);
    for (int v : neighbours[u])
      if (v != heavySon[u] && !visited[v]) {
        chainCount++;
        chains[chainCount].master = u;
        chains[chainCount].headDepth = depthU;
        chains[chainCount].head = v;
        dfsHeavy(v, depthU + 1);
      }
  }
}

int maxPath(int u, int v) {
  if (chainId[u] == chainId[v]) {
    if (position[u] < position[v])
      return query(position[u], position[v]);
    else
      return query(position[v], position[u]);
  } else {
    if (chains[chainId[v]].headDepth > chains[chainId[u]].headDepth)
      std::swap(u, v);
    return std::max(maxPath(chains[chainId[u]].master, v),
                    query(position[chains[chainId[u]].head], position[u]));
  }
}

int updateAdd(int u, int add) {
  update(position[u], add);
}

int main() {
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);
  int Q;
  scanf("%d%d", &N, &Q);
  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);
    neighbours[x].push_back(y);
    neighbours[y].push_back(x);
  }
  Size[0] = 0;
  dfsSize(1);
  for (int i = 1; i <= N; i++)
    visited[i] = false;
  chainCount = 0;
  chains[chainCount].master = 0;
  chains[chainCount].headDepth = 1;
  chains[chainCount].head = 1;
  chainCount++;
  dfsHeavy(1, 1);
  int j = 0;
  for (int i : heavyTraversal) {
    j++;
    updateAdd(j, i);
  }
  for (int i = 1; i <= Q; i++) {
    int x, y, q;
    scanf("%d%d%d", &q, &x, &y);
    if (q == 0)
      updateAdd(x, y);
    else
      printf("%d\n", maxPath(x, y));
  }
  return 0;
}