Cod sursa(job #2876985)

Utilizator Alex_tz307Lorintz Alexandru Alex_tz307 Data 23 martie 2022 23:29:09
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.47 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

const int NMAX = 1e5 + 5;
int a[NMAX];

struct SegTree {
  int Size;
  vector<int> tree;

  void init(int N) {
    Size = 1;
    while (Size < N)
      Size <<= 1;
    tree.resize(Size << 1 | 1);
  }

  void build(int x, int lx, int rx) {
    if (lx == rx) {
      tree[x] = a[lx];
      return;
    }
    int mid = (lx + rx) >> 1;
    build(x << 1, lx, mid);
    build(x << 1 | 1, mid + 1, rx);
    tree[x] = max(tree[x << 1], tree[x << 1 | 1]);
  }

  void update(int x, int lx, int rx, int poz, int val) {
    if (lx == rx) {
      tree[x] = val;
      return;
    }
    int mid = (lx + rx) >> 1;
    if (poz <= mid)
      update(x << 1, lx, mid, poz, val);
    else
      update(x << 1 | 1, mid + 1, rx, poz, val);
    tree[x] = max(tree[x << 1], tree[x << 1 | 1]);
  }

  int query(int x, int lx, int rx, int st, int dr) {
    if (st <= lx && rx <= dr)
      return tree[x];
    int mid = (lx + rx) >> 1, ans1 = 0, ans2 = 0;
    if (st <= mid)
      ans1 = query(x << 1, lx, mid, st, dr);
    if (mid < dr)
      ans2 = query(x << 1 | 1, mid + 1, rx, st, dr);
    return max(ans1, ans2);
  }
} tree;

int N, Q, v[NMAX]; /// numarul de noduri, de query-uri, valorile initiale
vector<int> G[NMAX]; /// arborele
int p[NMAX]; /// tatal nodului
int sz[NMAX]; /// dimensiunea subarborelui cu radacina in nod
int depth[NMAX]; /// adancimea / nivelul in arbore
int chain_top[NMAX]; /// capul chain-ului(cel mai apropiat de radacina nod din chain)
int cnt_labels, label[NMAX]; /// le voi da nodurilor valori astfel incat sa am chain-urile numerotate consecutiv sa pot face aint pe ele

void read_input() {
  fin >> N >> Q;
  for (int i = 1; i <= N; ++i)
    fin >> v[i];
  for (int i = 1; i < N; ++i) {
    int x, y;
    fin >> x >> y;
    G[x].emplace_back(y);
    G[y].emplace_back(x);
  }
}

void dfs_init(int u, int parent) {
  p[u] = parent;
  depth[u] = depth[parent] + 1;
  sz[u] = 1;
  chain_top[u] = u;
  for (int v : G[u])
    if (v != parent) {
      dfs_init(v, u);
      sz[u] += sz[v];
    }
}

void dfs_heavy(int u) {
  label[u] = ++cnt_labels;
  int max_size = -1, heavy_son = -1;
  for (int v : G[u])
    if (v != p[u] && sz[v] > max_size) {
      max_size = sz[v];
      heavy_son = v;
    }
  if(heavy_son == -1)
    return;
  chain_top[heavy_son] = chain_top[u];
  dfs_heavy(heavy_son);
  for (int v : G[u])
    if (v != p[u] && v != heavy_son)
      dfs_heavy(v);
}

int lca_query(int x, int y) {
  if (chain_top[x] == chain_top[y]) { /// x si y fac parte din acelasi chain
    if (label[x] > label[y])
      swap(x, y);
    return tree.query(1, 1, N, label[x], label[y]);
  }
  if (depth[chain_top[x]] > depth[chain_top[y]])
    return max(tree.query(1, 1, N, label[chain_top[x]], label[x]), lca_query(p[chain_top[x]], y));
  return max(tree.query(1, 1, N, label[chain_top[y]], label[y]), lca_query(x, p[chain_top[y]]));
}

void solve() {
  dfs_init(1, 0);
  dfs_heavy(1);
  tree.init(N);
  for (int i = 1; i <= N; ++i)
    a[label[i]] = v[i];
  tree.build(1, 1, N);
  for (int q = 0; q < Q; ++q) {
    int op, x, y;
    fin >> op >> x >> y;
    if (op == 0)
      tree.update(1, 1, N, label[x], y);
    else
      fout << lca_query(x, y) << '\n';
  }
}

void close_files() {
  fin.close();
  fout.close();
}

int main() {
  read_input();
  solve();
  close_files();
  return 0;
}