Cod sursa(job #2748621)

Utilizator MoodyFaresFares Mohamad MoodyFares Data 1 mai 2021 21:40:20
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.02 kb
#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

const int MAX_N = 100000;

struct Chain {
  int head;
  int dad;
  int dadDepth;

  Chain() {
    head = 1;
    dad = 0;
    dadDepth = 0;
  }
};

int n;
int a[1 + MAX_N];
vector<int> g[1 + MAX_N];
bool viz[1 + MAX_N];
int treeSize[1 + MAX_N];
vector<int> heavyPath;
int heavySon[1 + MAX_N];
int posHeavyPath[1 + MAX_N];
int chainCount = 1;
int chainId[1 + MAX_N];
Chain chain[1 + MAX_N];
int arbint[1 + 4 * MAX_N];

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

int query(int nod, int a, int b, int st, int dr) {
  if(a <= st && dr <= b)
    return arbint[nod];
  int sol1 = 0, sol2 = 0;
  int mij = (st + dr) / 2;
  if(a <= mij)
    sol1 = query(nod * 2, a, b, st, mij);
  if(mij < b)
    sol2 = query(nod * 2 + 1, a, b, mij + 1, dr);
  return max(sol1, sol2);
}

void dfsSize(int v) {
  viz[v] = true;
  treeSize[v] = 1;
  for (auto u : g[v]) {
    if (!viz[u]) {
      dfsSize(u);
      treeSize[v] += treeSize[u];
      if (treeSize[heavySon[v]] < treeSize[u])
        heavySon[v] = u;
    }
  }
}

void dfsHeavy(int v, int depth) {
  if (v == 7) {
    v++;
    v--;
  }
  viz[v] = true;
  heavyPath.push_back(v);
  posHeavyPath[v] = (int)heavyPath.size();
  chainId[v] = chainCount;
  if (heavySon[v] != 0) {
    dfsHeavy(heavySon[v], depth + 1);
    for (auto u : g[v]) {
      if (!viz[u] && u != heavySon[v]) {
        chainCount++;
        chain[chainCount].head = u;
        chain[chainCount].dad = v;
        chain[chainCount].dadDepth= depth;
        dfsHeavy(u, depth + 1);
      }
    }
  }
}


int pathMax(int u, int v) {
  if (chainId[u] == chainId[v])
    return query(1, min(posHeavyPath[u], posHeavyPath[v]), max(posHeavyPath[u], posHeavyPath[v]), 1, n);
  else {
    if (chain[chainId[u]].dadDepth < chain[chainId[v]].dadDepth)
      swap(u, v);
    int tempAns = query(1, posHeavyPath[chain[chainId[u]].head], posHeavyPath[u], 1, n);
    return max(tempAns, pathMax(chain[chainId[u]].dad, v));
  }
}

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

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

  dfsSize(1);
  for (int i = 1; i <= n; i++)
    viz[i] = false;
  dfsHeavy(1, 1);
  int pos = 0;
  for (auto it : heavyPath)
    update(1, ++pos, a[it], 1, n);

  for (int i = 1; i <= m; i++) {
    int t, x, y;
    scanf("%d%d%d", &t, &x, &y);
    if (t == 0)
      update(1, posHeavyPath[x], y, 1, n);
    else
      printf("%d\n", pathMax(x, y));
  }
  return 0;
}