Cod sursa(job #3144574)

Utilizator NanuGrancea Alexandru Nanu Data 8 august 2023 21:49:44
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.96 kb
#include <fstream>
#include <vector>
using namespace std;

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

#define DIM 100000

int n, q, lant, id;
int v[DIM + 5];
int w[DIM + 5];             //cati descendenti are nodul i.
int poz[DIM + 5];
int tata[DIM + 5];
int level[DIM + 5];
int chain[DIM + 5];         //din ce lant face parte nodul i;
int first[DIM + 5];         //primul nod din fiecare lant;
int Sonmax[DIM + 5];        //fiul care are cei mai multi descendenti.
int tree[4 * DIM + 5];  
int size_chain[DIM + 5];    //lungimea lantului actual.   
vector <int> G[DIM + 5];

static inline void Update_tree(int st, int dr, int nod, int poz, int val) {
  if(st == dr) 
    tree[nod] = val;
  else {
    int mid = (st + dr) >> 1;
    if(poz <= mid)
      Update_tree(st, mid, nod * 2, poz, val);
    else Update_tree(mid + 1, dr, nod * 2 + 1, poz, val);

    tree[nod] = max(tree[nod * 2], tree[nod * 2 + 1]);
  }
}

static inline int Query_tree(int st, int dr, int nod, int left, int right) {
  if(left <= st && dr <= right)
    return tree[nod];

  int mid = (st + dr) >> 1;
  int max1 = 0, max2 = 0;

  if(left <= mid)
    max1 = Query_tree(st, mid, nod * 2, left, right);
  if(mid < right)
    max2 = Query_tree(mid + 1, dr, nod * 2 + 1, left, right);

  return max(max1, max2); 
}

static inline void dfs(int nod, int t) {
  tata[nod] = t;
  Sonmax[nod] = -1;
  w[nod] = 1;       //el insusi.
  level[nod] = level[t] + 1;

  for(auto e : G[nod])
    if(e != t) {
      dfs(e, nod);

      if(Sonmax[nod] == -1 || w[Sonmax[nod]] < w[e])
        Sonmax[nod] = e;   //fiul care are cei mai multi descendenti.

      w[nod] += w[e];   
    }
}

static inline void Split(int nod) {
  chain[nod] = lant;
  poz[nod] = ++id;
  size_chain[lant]++;

  if(Sonmax[nod] == -1)   //daca e frunza;
    return;

  Split(Sonmax[nod]);

  for(auto e : G[nod]) 
    if(e != tata[nod] && e != Sonmax[nod]) {
      
      lant++;
      first[lant] = e;
      Split(e);
    }
}

static inline void Heavy_path() {
  dfs(1, 0);

  first[1] = 1;
  lant = 1;
  Split(1);

  for(int i = 1; i <= n; i++)
    Update_tree(1, n, 1, poz[i], v[i]);
}

static inline int Query(int x, int y) {
  if(chain[x] == chain[y])
    return Query_tree(1, n, 1, min(poz[x], poz[y]), max(poz[x], poz[y]));

  if(level[first[chain[x]]] < level[first[chain[y]]])
    swap(x, y);
  
  int ans = Query_tree(1, n, 1, poz[first[chain[x]]], poz[x]);  
  return max(ans, Query(tata[first[chain[x]]], y));
}

int main() {
  fin.tie(0), fout.tie(0);

  fin >> n >> q;
  for(int i = 1; i <= n; i++) 
    fin >> v[i];

  for(int i = 1, x, y; i < n; i++) {
    fin >> x >> y;

    G[x].push_back(y);
    G[y].push_back(x);
  }

  Heavy_path();

  for(int i = 1, tip, x, y; i <= q; i++) {
    fin >> tip >> x >> y;

    if(tip == 0)  
      Update_tree(1, n, 1, poz[x], y);
    else fout << Query(x, y) << '\n';
  }

  return 0;
}