Cod sursa(job #2668985)

Utilizator DenisONIcBanu Denis Andrei DenisONIc Data 5 noiembrie 2020 19:53:25
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.22 kb
#include <bits/stdc++.h>
using namespace std;
void debug_out() { cerr << endl; }
template<class T> ostream& prnt(ostream& out, T v) { out << v.size() << '\n'; for(auto e : v) out << e << ' '; return out;}
template<class T> ostream& operator<<(ostream& out, vector <T> v) { return prnt(out, v); }
template<class T> ostream& operator<<(ostream& out, set <T> v) { return prnt(out, v); }
template<class T1, class T2> ostream& operator<<(ostream& out, map <T1, T2> v) { return prnt(out, v); }
template<class T1, class T2> ostream& operator<<(ostream& out, pair<T1, T2> p) { return out << '(' << p.first << ' ' << p.second << ')'; }
template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) { cerr << " " << H; debug_out(T...);}
#define dbg(...) cerr << #__VA_ARGS__ << " ->", debug_out(__VA_ARGS__)
#define dbg_v(x, n) do{cerr<<#x"[]: ";for(int _=0;_<n;++_)cerr<<x[_]<<" ";cerr<<'\n';}while(0)
#define dbg_ok cerr<<"OK!\n"
#define ll long long
#define ld long double
#define ull unsigned long long
#define pii pair<int,int>
#define MOD 1000000007
#define zeros(x) x&(x-1)^x
#define fi first
#define se second
#define NMAX 500005
const long double PI = acos(-1);

template <class T>
class SegmentTree{
  int n;
public:
  vector<int> t;
  
  void build() {  // build the tree
    for (int i = n - 1; i > 0; --i) t[i] = max(t[i<<1], t[i<<1|1]); // pentru suma schimba aici
  }


  void init(int n){
    this->n = n;
    t.resize(2 * n);
  }

  void set(int p, int value) {  // set value at position p
    for (t[p += n] = value; p > 1; p >>= 1) t[p>>1] = max(t[p], t[p^1]); // pentru suma schimba aici
  }

  int query(int l, int r) {  // max on interval [l, r)
    int res = 0;
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if (l&1) res = max(res, t[l++]); // pentru suma schimba aici
      if (r&1) res = max(res, t[--r]); // pentru suma schimba aici
    }
    return res;
  }
};

template <class T, int V>
class HeavyLight {
  int parent[V], heavy[V], depth[V];
  int root[V], treePos[V];
  SegmentTree<T> tree;

  template <class G>
  int dfs(const G& graph, int v) {
    int size = 1, maxSubtree = 0;
    for (int u : graph[v]) if (u != parent[v]) {
      parent[u] = v;
      depth[u] = depth[v] + 1;
      int subtree = dfs(graph, u);
      if (subtree > maxSubtree) heavy[v] = u, maxSubtree = subtree;
      size += subtree;
    }
    return size;
  }

  template <class BinaryOperation>
  void processPath(int u, int v, BinaryOperation op) {
    for (; root[u] != root[v]; v = parent[root[v]]) {
      if (depth[root[u]] > depth[root[v]]) swap(u, v);
      op(treePos[root[v]], treePos[v] + 1);
    }
    if (depth[u] > depth[v]) swap(u, v);
    op(treePos[u], treePos[v] + 1);
  }

public:
  // vector<vector<int>> graph
  // indexat de la 0
  template <class G>
  void init(const G& graph) {
    int n = graph.size();
    fill_n(heavy, n, -1);
    parent[0] = -1;
    depth[0] = 0;
    dfs(graph, 0);
    for (int i = 0, currentPos = 0; i < n; ++i)
      if (parent[i] == -1 || heavy[parent[i]] != i)
        for (int j = i; j != -1; j = heavy[j]) {
          root[j] = i;
          treePos[j] = currentPos++;
        }
    tree.init(n);
  }

  void set(int v, const T& value) {
    tree.set(treePos[v], value);
  }

  void modifyPath(int u, int v, const T& value) {
    processPath(u, v, [this, &value](int l, int r) { tree.modify(l, r, value); });
  }

  T queryPath(int u, int v) {
    T res = T();
    processPath(u, v, [this, &res](int l, int r) { res = max(res, tree.query(l, r)); }); // face maxim, daca vrei altceva schimba
    return res;
  }
};
HeavyLight<int, NMAX> hld;


int n, m, x, v[NMAX];
vector<vector<int>> g;

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

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

  g.resize(n);
  
  for (int i=0;i<n;i++){
    scanf("%d", &v[i]);
  }

  for (int i=1;i<n;i++){
    int y;
    scanf("%d%d", &x, &y);
    cin >> x >> y;
    x--;
    y--;
    g[x].push_back(y);
    g[y].push_back(x);
  }

  hld.init(g);

  for (int i=0;i<n;i++){
    hld.set(i, v[i]);
  }

  for (int i=1;i<=m;i++){
    int t,y;
    scanf("%d%d%d", &t, &x, &y);
    if (t == 0){
      x--;
      hld.set(x, y);
    }
    else{
      x--; y--;
      cout << hld.queryPath(x,y) << '\n';
    }
  }

  return 0;
}