Cod sursa(job #3171165)

Utilizator IanisBelu Ianis Ianis Data 18 noiembrie 2023 14:12:14
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.19 kb
#ifdef LOCAL
#include <iostream>
#include <fstream>
#else
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define endl '\n'
#endif

#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

#define fi first
#define se second

#define lsb(x) (x & (-x))

using namespace std;

template <typename T>
bool ckmax(T &a, T b) { return a < b ? a = b, true : false; }
template <typename T>
bool ckmin(T &a, T b) { return a > b ? a = b, true : false; }

typedef long long ll;
typedef pair<int, int> pii;

const int NMAX = 1e5+5;

#ifdef LOCAL
ifstream fin("input.txt");
#define fout cout
#else
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
#endif

struct SegTree {
   int n;
   vector<int> aint;

   SegTree() { }
   SegTree(int _n): n(_n), aint(4 * (_n + 5)) { }

   void update(int node, int l, int r, int pos, int val) {
      if (l >= r) {
         aint[node] = val;
         return;
      }

      int mid = (l + r) >> 1;

      if (pos <= mid)
         update(node * 2, l, mid, pos, val);
      else
         update(node * 2 + 1, mid + 1, r, pos, val);

      aint[node] = max(aint[node * 2], aint[node * 2 + 1]);
   }

   void update(int pos, int val) {
      update(1, 1, n, pos, val);
   }

   int query(int node, int l, int r, int ll, int rr) {
      if (ll <= l && r <= rr)
         return aint[node];

      int mid = (l + r) >> 1;
      int mx = 0;

      if (ll <= mid)
         mx = query(node * 2, l, mid, ll, rr);
      if (mid < rr)
         ckmax(mx, query(node * 2 + 1, mid + 1, r, ll, rr));

      return mx;
   }

   int query(int l, int r) {
      return query(1, 1, n, l, r);
   }
};

int n, q;
int a[NMAX];
vector<int> g[NMAX];
int daddy[NMAX], depth[NMAX];
int heavy[NMAX], head[NMAX], pos[NMAX];
SegTree seg_tree;

int dfs(int x = 1) {
   int size = 1;
   int mx = 0;

   for (auto &it : g[x]) {
      if (it == daddy[x])
         continue;
      daddy[it] = x;
      depth[it] = depth[x] + 1;

      int child_size = dfs(it);
      size += child_size;

      if (ckmax(mx, child_size))
         heavy[x] = it;
   }

   return size;
}

void heavy_decomp(int x = 1, int h = 1) {
   static int cnt = 0;

   head[x] = h;
   pos[x] = ++cnt;

   if (heavy[x])
      heavy_decomp(heavy[x], h);

   for (auto &it : g[x]) {
      if (it == daddy[x] || it == heavy[x])
         continue;
      heavy_decomp(it, it);
   }
}

void update(int x, int y) {
   seg_tree.update(pos[x], y);
}

int query(int x, int y) {
   int ans = 0;

   while (head[x] != head[y]) {
      if (depth[head[x]] < depth[head[y]])
         swap(x, y);
      ans = max(ans, seg_tree.query(pos[head[x]], pos[x]));
      x = daddy[head[x]];
   }

   if (depth[x] < depth[y])
      swap(x, y);

   return max(ans, seg_tree.query(pos[y], pos[x]));
}

signed main() {
   fin >> n >> q;
   for (int i = 1; i <= n; i++)
      fin >> a[i];
   for (int i = 1, x, y; i < n; i++) {
      fin >> x >> y;
      g[x].push_back(y);
      g[y].push_back(x);
   }

   dfs();
   heavy_decomp();
   daddy[1] = 1;

   seg_tree = SegTree(n);
   for (int i = 1; i <= n; i++)
      seg_tree.update(pos[i], a[i]);

   while (q--) {
      int t, x, y;
      fin >> t >> x >> y;
      if (t == 0) update(x, y);
      else fout << query(x, y) << endl;
   }

   return 0;
}