Cod sursa(job #2272080)

Utilizator Robert_VRVRobert Vadastreanu Robert_VRV Data 29 octombrie 2018 17:54:00
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.39 kb
#include <stdio.h>
#include <vector>

const int MAX_N = 100000;

int N, Q;

std::vector<int> neighbours[1 + MAX_N];
std::vector<int> heavyTraversal;
int position[1 + MAX_N], heavySon[1 + MAX_N], Size[1 + MAX_N];
bool visited[1 + MAX_N];
int ArbInt[4 * MAX_N], val[1 + MAX_N];

struct Chain {
  int head;
  int father;
  int fatherDepth;
};

int chainId[1 + MAX_N];
int chainCount;
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 ans = 0;
  if (begin <= mid)
    ans = std::max(ans, query(2 * nod, st, mid, begin, end));
  if (mid < end)
    ans = std::max(ans, query(2 * nod + 1, mid + 1, dr, begin, end));
  return ans;
}

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].father = u;
        chains[chainCount].fatherDepth = 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]].fatherDepth > chains[chainId[u]].fatherDepth)
      std::swap(u, v);
    int ans1 = maxPath(chains[chainId[u]].father, v);
    int ans2 = query(position[chains[chainId[u]].head], position[u]);
    return std::max(ans1, ans2);
  }
}

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

int main() {

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

  scanf("%d%d", &N, &Q);
  for (int i = 1; i <= N; i++)
    scanf("%d", &val[i]);
  for (int i = 1; i < N; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    neighbours[u].push_back(v);
    neighbours[v].push_back(u);
  }

  Size[0] = 0;
  dfsSize(1);
  for (int i = 1; i <= N; i++)
    visited[i] = false;
  chainCount = 1;
  chains[chainCount].father = 0;
  chains[chainCount].fatherDepth = 0;
  chains[chainCount].head = 1;
  dfsHeavy(1, 1);

  int j = 0;
  for (int i : heavyTraversal)
    update(++j, i);

  for (int i = 1; i <= Q; i++) {
    int q, x, y;
    scanf("%d%d%d", &q, &x, &y);
    if (q == 0) {
      updateNode(x, y);
    } else if (q == 1) {
      printf("%d\n", maxPath(x, y));
    }
  }

  fclose(stdin);
  fclose(stdout);

  return 0;
}