Cod sursa(job #2687420)

Utilizator popashtefan10Popa Stefan popashtefan10 Data 20 decembrie 2020 09:24:00
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.7 kb
#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

const int LOGN = 16;
const int NMAX = 100000;

class aint {
private:
  vector<int> maxim;

  void upd(int nod, int nst, int ndr, int upoz, int val) {
    if(nst == ndr)
      maxim[nod] = val;
    else {
      int mij = (nst + ndr) / 2;
      if(upoz <= mij)
        upd(2 * nod, nst, mij, upoz, val);
      else
        upd(2 * nod + 1, mij + 1, ndr, upoz, val);
      maxim[nod] = max(maxim[2 * nod], maxim[2 * nod + 1]);
    }
  }

  int qry(int nod, int nst, int ndr, int qst, int qdr) {
    if(qst > ndr || qdr < nst) return 0;
    if(nst >= qst && ndr <= qdr) return maxim[nod];

    int mij = (nst + ndr) / 2;
    return max(qry(2 * nod, nst, mij, qst, qdr), qry(2 * nod + 1, mij + 1, ndr, qst, qdr));
  }

public:
  int sz;

  void init(vector<int> &v, int nod, int nst, int ndr) {
    if(nst == ndr)
      maxim[nod] = v[nst];
    else {
      int mij = (nst + ndr) / 2;
      init(v, 2 * nod, nst, mij);
      init(v, 2 * nod + 1, mij + 1, ndr);
      maxim[nod] = max(maxim[2 * nod], maxim[2 * nod + 1]);
    }
  }

  aint() {
    sz = 0;
  }

  aint(vector<int> &v) {
    sz = v.size();
    maxim.resize(4 * v.size());
    init(v, 1, 0, v.size() - 1);
  }

  void update(int poz, int val) {
    upd(1, 0, sz - 1, poz, val);
  }

  int query(int qst) {
    return qry(1, 0, sz - 1, qst, sz - 1);
  }

  int query(int qst, int qdr) {
    return qry(1, 0, sz - 1, qst, qdr);
  }
};

int n, m;
int val[NMAX + 5], path[NMAX + 5], path_poz[NMAX + 5], h[NMAX + 5];
vector<int> arb[NMAX + 5], path_dad;
vector<aint> aints;
vector<vector<int>> paths;

int path_decomposition(int nod, int dad) {
  bool frunza = true;
  int fii = 1, max_fii = 0, heaviest = -1;
  h[nod] = h[dad] + 1;

  for(int vec: arb[nod])
    if(vec != dad) {
      frunza = false;
      int fii_vec = path_decomposition(vec, nod);
      fii += fii_vec;

      if(fii_vec > max_fii) {
        max_fii = fii_vec;
        heaviest = path[vec];
      }
    }

  if(!frunza) {
    paths[heaviest].push_back(nod);
    path[nod] = heaviest;
    path_poz[nod] = paths[heaviest].size() - 1;
    path_dad[heaviest] = dad;
  }
  else {
    vector<int> new_path;
    paths.push_back(new_path);
    paths.back().push_back(nod);

    path_dad.push_back(dad);
    path[nod] = paths.size() - 1;
    path_poz[nod] = 0;
  }

  return fii;
}

int query(int nod1, int nod2) {
  int ans = 0;

  while(path[nod1] != path[nod2])
    if(h[path_dad[path[nod1]]] >= h[path_dad[path[nod2]]]) {
      ans = max(ans, aints[path[nod1]].query(path_poz[nod1]));
      nod1 = path_dad[path[nod1]];
    }
    else {
      ans = max(ans, aints[path[nod2]].query(path_poz[nod2]));
      nod2 = path_dad[path[nod2]];
    }

  if(path_poz[nod1] > path_poz[nod2]) swap(nod1, nod2);
  ans = max(ans, aints[path[nod1]].query(path_poz[nod1], path_poz[nod2]));
  return ans;
}

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

  scanf("%d %d", &n, &m);
  for(int i = 1; i <= n; i++)
    scanf("%d", &val[i]);
  for(int i = 1; i < n; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    arb[x].push_back(y);
    arb[y].push_back(x);
  }

  path_decomposition(1, 0);

  for(int i = 0; i < paths.size(); i++) {
    vector<int> vpath;
    for(int crt: paths[i])
      vpath.push_back(val[crt]);
    aint new_aint = aint(vpath);
    aints.push_back(new_aint);
  }

  for(int i = 1; i <= m; i++) {
    int t, x, y;
    scanf("%d %d %d", &t, &x, &y);

    if(t == 0)
      aints[path[x]].update(path_poz[x], y);
    else
      printf("%d\n", query(x, y));
  }

  return 0;
}