Cod sursa(job #2981866)

Utilizator andreic06Andrei Calota andreic06 Data 18 februarie 2023 21:13:25
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.03 kb
#include <bits/stdc++.h>

using namespace std;
const int N_MAX = 1e5;
const int INF = 2e9;
const int NONE = -1;

int DS[2 * N_MAX], input[N_MAX];
void build_up (int node, int left, int right) {
    if (left == right)
      DS[node] = input[left];
    else {
      int mid = left + (right - left) / 2;
      build_up (node + 1, left, mid);
      build_up (node + 2 * (mid - left + 1), mid + 1, right);

      DS[node] = max (DS[node + 1], DS[node + 2 * (mid - left + 1)]);
    }
}

void update (int node, int left, int right, int pos, int value) {
    if (left == right)
      DS[node] = value;
    else {
      int mid = left + (right - left) / 2;
      if (pos <= mid)
        update (node + 1, left, mid, pos, value);
      else
        update (node + 2 * (mid - left + 1), mid + 1, right, pos, value);

      DS[node] = max (DS[node + 1], DS[node + 2 * (mid - left + 1)]);
    }
}

int query (int node, int left, int right, int qleft, int qright) {
   if (qleft <= left && right <= qright)
     return DS[node];
   int mid = left + (right - left) / 2;

   int answer = -INF;
   if (qleft <= mid)
     answer = max (answer, query (node + 1, left, mid, qleft, qright));
   if (mid + 1 <= qright)
     answer = max (answer, query (node + 2 * (mid - left + 1), mid + 1, right, qleft, qright));
   return answer;
}

int cost[N_MAX]; int n, q;
vector<int> tree[N_MAX];

int depth[N_MAX], sizof[N_MAX];
int start[N_MAX], posof[N_MAX];
int heavy_child[N_MAX], parent[N_MAX];

void dfs (int root, int p) {
   depth[root] = depth[p] + 1;
   parent[root] = p;
   for (int node : tree[root])
      if (node != p)
        dfs (node, root);
   sizof[root] = 1;
   for (int node : tree[root])
      if (node != p)
        sizof[root] += sizof[node];
}

void decompose (int root, int p, int curr_start) {
   start[root] = curr_start;

   int winner = NONE, maxSize = 0;
   for (int node : tree[root])
      if (node != p)
        if (maxSize < sizof[node])
          maxSize = sizof[node], winner = node;

   heavy_child[root] = winner;
   for (int node : tree[root])
      if (node != p) {
        if (node == winner)
          decompose (node, root, curr_start);
        else
          decompose (node, root, node);
     }
}

void construct_chain () {
   for (int node = 0; node < n; node ++) {
      posof[node] = NONE;
      heavy_child[node] = NONE;
   }

   decompose (0, NONE, 0);
   int curr_pos = 0;
   for (int node = 0; node < n; node ++) {
      if (start[node] == node) {
        int aux = node;
        do {
          posof[aux] = curr_pos ++;
          aux = heavy_child[aux];
        }
        while (aux != NONE);
      }
   }
}

void HLD_update (int node, int new_value) {
    input[posof[node]] = new_value;
    update (0, 0, n - 1, posof[node], new_value);
}

int HLD_query (int u, int v) {
   int answer = -INF;
   while (start[u] != start[v]) {
      if (depth[start[u]] < depth[start[v]])
        swap (u, v);
      answer = max (answer, query (0, 0, n - 1, posof[start[u]], posof[u]));
      u = parent[start[u]];
    }
    if (posof[u] > posof[v])
      swap (u, v);
    answer = max (answer, query (0, 0, n - 1, posof[u], posof[v]));
    return answer;
}

int main()
{
   ifstream in ("heavypath.in");
   ofstream out ("heavypath.out");

   in >> n >> q;
   for (int node = 0; node < n; node ++)
      in >> cost[node];
   for (int i = 0; i < n - 1; i ++) {
      int u, v; in >> u >> v; u --, v --;
      tree[u].push_back (v);
      tree[v].push_back (u);
   }

   dfs (0, NONE);
   decompose (0, NONE, 0);
   construct_chain ();

   for (int node = 0; node < n; node ++)
      input[posof[node]] = cost[node];
   build_up (0, 0, n - 1);

   for (int i = 0; i < q; i ++) {
      int t; in >> t;
      if (t == 0) {
        int node, new_value; in >> node >> new_value; node --;
        HLD_update (node, new_value);
      }
      else {
        int u, v; in >> u >> v; u --, v --;
        out << HLD_query (u, v) << "\n";
      }
   }
    return 0;
}