Cod sursa(job #2241768)

Utilizator LucaSeriSeritan Luca LucaSeri Data 16 septembrie 2018 22:12:18
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.52 kb
#include <stdio.h>
#include <vector>
#include <algorithm>

using namespace std;

const int MAXN = 1e5;
const int MAXM = 1e5;
const int MAXVAL = 2e9;

int n, m;
vector<int> g[MAXN + 1];

class Node{
public :
  int val;
  int sub;
  int niv;
  int par;
  int pat;
  int pos;

  Node() {
    val = 0;
    sub = 0;
    niv = 0;
    par = 0;
    pat = 0;
    pos = 0;
  }
};

vector<Node> nodes(MAXN + 1);

class Path{
public :
  vector<int> P, T;
  int par;
  int cur;

  Path() {
    P.clear();
    T.clear();
    par = 0;
  }

  void update(int node, int st, int dr, int poz, int val) {
    if (st == dr) {
      T[node] = val;
      return;
    }
    int mij = (st + dr) / 2;
    if (poz <= mij) update(node << 1, st, mij, poz, val);
    else update((node << 1) | 1, mij + 1, dr, poz, val);
    T[node] = max(T[node << 1], T[(node << 1) | 1]);
  }

  int query(int node, int st, int dr, int a, int b) {
    if (a <= st && dr <= b) return T[node];
    int mij = (st + dr) / 2;
    int le = 0, ri = 0;
    if (a <= mij) le = query(node << 1, st, mij, a, b);
    if (mij < b) ri = query((node << 1) | 1, mij + 1, dr, a, b);
    return max(le, ri);
  }

  void addToPath(int node) {
    P.push_back(node);
  }

  void reversePathAndMakeTree() {
    reverse(P.begin(), P.end());
    int nn = 1;
    while(nn < P.size()) nn <<= 1;
    nn <<= 1;
    T.resize(nn );
    for (int i = 1; i <= P.size(); ++ i) {
      nodes[P[i - 1]].pos = i;
      update(1, 1, P.size(), nodes[P[i - 1]].pos, nodes[P[i - 1]].val);
    }
  }

};

vector<Path> paths;

void makePaths(int node, int prev, int niv) {
  nodes[node].niv = niv;
  nodes[node].par = prev;

  int connect = 0, maxsub = 0;
  for (auto x : g[node]) {
    if (x == prev) continue;
    makePaths(x, node, niv + 1);
    nodes[node].sub += nodes[x].sub + 1;
    if (maxsub < nodes[x].sub + 1) {
      maxsub = nodes[x].sub;
      connect = x;
    }
  }

  if (connect) {
    nodes[node].pat = nodes[connect].pat;
    paths[nodes[node].pat].par = prev;
    paths[nodes[node].pat].addToPath(node);
  }
  else {
    Path aux;
    aux.addToPath(node);
    aux.par = prev;
    nodes[node].pat = paths.size();
    paths.push_back(aux);
  }
}

void reversePathsAndMakeTrees() {
  for (auto &x : paths)
    x.reversePathAndMakeTree();
}

void solve0(int a, int b) {
  nodes[a].val = b;
  paths[nodes[a].pat].update(1, 1, paths[nodes[a].pat].P.size(), nodes[a].pos, nodes[a].val);
}

int solve1(int a, int b) {
  int ans = -1;
  while (nodes[a].pat != nodes[b].pat) {
    if (nodes[paths[nodes[a].pat].par].niv < nodes[paths[nodes[b].pat].par].niv)
        swap(a, b);

        ans = max(paths[nodes[a].pat].query(1, 1, paths[nodes[a].pat].P.size(), 1, nodes[a].pos), ans);
        a = paths[nodes[a].pat].par;
  }

  return max(ans, paths[nodes[a].pat].query(1, 1, paths[nodes[a].pat].P.size(), min(nodes[a].pos, nodes[b].pos), max(nodes[a].pos, nodes[b].pos)));
}

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

  scanf("%d%d\n", &n, &m);

  for (int i = 1; i <= n; ++ i) scanf("%d ", &nodes[i].val);

  for (int i = 1; i < n; ++ i) {
    int a, b;
    scanf("%d%d", &a, &b);
    g[a].push_back(b);
    g[b].push_back(a);
  }

  makePaths(1, 1, 1);
  reversePathsAndMakeTrees();

  int t, a, b;
  for (int i = 1; i <= m; ++ i) {
    scanf("%d%d%d", &t, &a, &b);
    if (t)
      printf("%d\n", solve1(a, b));
    else
      solve0(a, b);
  }
  return 0;
}