Cod sursa(job #3042063)

Utilizator cadmium_Voicu Mihai Valeriu cadmium_ Data 3 aprilie 2023 21:17:21
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.09 kb
#include <bits/stdc++.h>
#define all(x) (x).begin(),(x).end()
using namespace std;

#ifndef DLOCAL
  #define cin fin
  #define cout fout
  ifstream cin("heavypath.in");
  ofstream cout("heavypath.out");
#endif

using ll = long long;

//#define int ll
#define sz(x) ((int)(x).size())

using pii = pair<int,int>;
using tii = tuple<int,int,int>;

const int nmax = 1e5 + 5, inf = 1e9 + 5;

template<typename Node>
struct AINT {
  vector<Node> aint;
  int n;
  void init(int nlen) {
    n = nlen;
    aint.resize(n * 4, Node());
  } 
  
  void upd(int p, Node x, int node, int cl, int cr) {
    if(p < cl || cr < p) return;
    if(cl == cr) { aint[node] = x; return; }
    int mid = cl + cr >> 1;
    upd(p, x, 2 * node, cl, mid);
    upd(p, x, 2 * node + 1, mid + 1, cr);
    aint[node] = aint[2 * node] + aint[2 * node + 1];
    return;
  }
  
  Node query(int l, int r, int node, int cl, int cr) {
    if(r < cl || cr < l) return Node();
    if(l <= cl && cr <= r) return aint[node];
    int mid = cl + cr >> 1;
    return query(l, r, 2 * node, cl, mid) + query(l, r, 2 * node + 1, mid + 1, cr);
  }
  
  Node query(int l, int r) {
    return query(l, r, 1, 1, n);
  }
  void upd(int p, Node x) {
    upd(p, x, 1, 1, n);
  }
};

struct Max {
  int val;
  Max(int x = -1): val(x) {;}
  Max operator + (const Max& x) const {
    return Max(max(x.val, val));
  }
};

vector<int> g[nmax];

namespace Tree {
  int pin[nmax], pout[nmax], inp = 1;
  int jump[nmax], p[nmax], d[nmax];
  
  AINT<Max> chains[nmax];
  int atrch[nmax], pinch[nmax], fch[nmax];
  int ptrch = 0;
  int area[nmax];
  void initarea(int node, int f) {
    pin[node] = inp++;
    d[node] = d[f] + 1;
    p[node] = f;
    jump[node] = f;
    if(d[jump[f]] - d[jump[jump[f]]] == d[f] - d[jump[f]])
      jump[node] = jump[jump[f]];
    //--
    area[node] = 1;
    for(auto x : g[node]) {
      if(x == f) continue;
      initarea(x, node);
      area[node] += area[x];
    }
    pout[node] = inp;
    return;
  }
  
  bool isanc(int f, int node) { return pin[f] <= pin[node] && pout[node] <= pout[f]; }
  int lca(int x, int y) {
    if(isanc(x, y)) return x;
    if(isanc(y, x)) return y;
    //cerr << x << ' ' << y << '\n';
    while(!isanc(x, y)) {
      //cerr << x << ' ' << y << '\n';
      if(!isanc(jump[x], y))
        x = jump[x];
      x = p[x];
    }
    return x;
  }
  
  void initch(int node, int f = -1) {
    //cerr << node << ' ' << f << ' ' << sz(g[node]) << '\n';
    if(sz(g[node]) == 1 && f != -1) { chains[atrch[node]].init(pinch[node]); return; }
    int heavyson = g[node][0] == f? g[node][1] : g[node][0];
    for(auto x : g[node]) {
      if(x == f) continue;
      if(area[x] > area[heavyson])
        heavyson = x;
    }
    
    pinch[heavyson] = pinch[node] + 1;
    atrch[heavyson] = atrch[node];
    initch(heavyson, node);
    
    for(auto x : g[node]) {
      if(x == f || x == heavyson) continue;
      pinch[x] = 1;
      atrch[x] = ++ptrch;
      fch[ptrch] = node;
      initch(x, node);
    }
    
    return;
  }
  
  Max querychain(int x, int l) {
    //cerr << x << ' ' << l << '\t' << atrch[x] << ' ' << pinch[l] << '\n';
    if(atrch[x] == atrch[l])
      return chains[atrch[x]].query(pinch[l], pinch[x]);
    return chains[atrch[x]].query(1, pinch[x]) + querychain(fch[atrch[x]], l);
  }
  
  int query(int x, int y) {
    int l = lca(x, y);
    return (querychain(x, l) + querychain(y, l)).val;
  }
  void upd(int x, int val) {
    //cerr << "aa\n";
    chains[atrch[x]].upd(pinch[x], val);
    //cerr << "paappa\n";
  }
}

signed main() {
  int n, q;
  cin >> n >> q;
  vector<int> values(n);
  for(auto &x : values) cin >> x;
  for(int i = 1, x, y; i < n; i++) {
    cin >> x >> y;
    g[x].emplace_back(y);
    g[y].emplace_back(x);
  }
  
  Tree::jump[1] = 1;
  Tree::d[1] = 0;
  Tree::initarea(1, 1);
  Tree::initch(1);
  for(int i = 1; i <= n; i++)
    Tree::upd(i, values[i - 1]);
  
  for(int i = 0, t, x, y; i < q; i++) {
    cin >> t >> x >> y;
    //cerr << "papa\n";
    if(t == 1)
      cout << Tree::query(x, y) << '\n';
    else
      Tree::upd(x, y);
  }
  
}

/**
      Vom spune că toamna a venit... foarte trist -
-- George Bacovia, Scântei galbene
*/