Cod sursa(job #3272533)

Utilizator Tudor__Holota Tudor-Matei Tudor__ Data 29 ianuarie 2025 18:36:19
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.93 kb
#include "bits/stdc++.h"
const int SIZE = 100000;
struct Node{
  std :: vector < int > adj;
  int val;
  int depth;
  int parent;
  int heavy;
  int head;
  int in;
  Node(): val(0), depth(0), parent(0), heavy(-1), head(0), in(0){}
};
int aint[4 * SIZE + 5];
Node nd[SIZE + 5];
int n, q;
//SegmentTree - START
void Update(int node, int left, int right, int idx, int val){
  if(left == right){
    aint[node] = val;
    return;
  }
  int mid = (left + right) >> 1;
  if(idx <= mid){
    Update(2 * node, left, mid, idx, val);
  }else{
    Update(2 * node + 1, mid + 1, right, idx, val);
  }
  aint[node] = std :: max(aint[2 * node], aint[2 * node + 1]);
}

int Query(int node, int left, int right, int L, int R){
  if(R < left or L  > right){
    return INT_MIN;
  }
  if(L <= left and right <= R){
    return aint[node];
  }
  int mid = (left + right) >> 1;
  int ansL = Query(2 * node, left, mid, L, R);
  int ansR = Query(2 * node + 1, mid + 1, right, L, R);
  return std :: max(ansL, ansR);
}
void Init(){
  for(int i = 1; i <= n; i++){
    Update(1, 1, n, nd[i].in, nd[i].val);
  }
}
//SegmentTree - STOP
//HLD - START
int Heavy_Dfs(int node){
  int my_size = 1, max_child_size = 0;
  for(int i : nd[node].adj){
    if(i != nd[node].parent){
      nd[i].parent = node;
      nd[i].depth = nd[node].depth + 1;
      int child_size = Heavy_Dfs(i);
      my_size += child_size;
      if(child_size > max_child_size){
        max_child_size = child_size;
        nd[node].heavy = i;
      }
    }
  }
  return my_size;
}

void Descompose_dfs(int node, int head){
  static int time = 0;
  nd[node].head = head;
  nd[node].in = ++time;
  if(nd[node].heavy != -1){
    Descompose_dfs(nd[node].heavy, head);
  }
  for(int i : nd[node].adj){
    if(i != nd[node].parent and i != nd[node].heavy){
      Descompose_dfs(i, i); // start a new path
    }
  }
}

int PathQuery(int a, int b){
  int result = INT_MIN;
  while(nd[a].head != nd[b].head){
    if(nd[nd[a].head].depth > nd[nd[b].head].depth){
      std :: swap(a, b);
    }
   result = std :: max(result, Query(1, 1, n, nd[nd[b].head].in, nd[b].in));
   b = nd[nd[b].head].parent;
  }

  if(nd[a].depth > nd[b].depth){
    std :: swap(a, b);
  }
  result = std :: max(result, Query(1, 1, n, nd[a].in, nd[b].in));
  return result;
}
// HLD - END
void Read(){
  std :: cin >> n >> q;
  for(int i = 1; i <= n; i++){
    std :: cin >> nd[i].val;
  }
  for(int i = 1; i < n; i++){
    int x, y;
    std :: cin >> x >> y;
    nd[x].adj.push_back(y);
    nd[y].adj.push_back(x);
  }
}
void ProcessQueries(){
  while(q -- ){
    int type, x, y;
    std :: cin >> type >> x >> y;
    if(type == 0){
      Update(1, 1, n, nd[x].in, y);
    }else{
      std :: cout << PathQuery(x, y) << '\n';
    }
  }
}
signed main(){
  std :: ios_base :: sync_with_stdio(false);
  std :: cin.tie(0);
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);
  Read();
  Heavy_Dfs(1);
  Descompose_dfs(1, 1);
  Init();
  ProcessQueries();
  return 0;
}