Cod sursa(job #2981863)

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

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

struct defST {
    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;
    }
} ST;


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

struct defHLD {
     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 update (int node, int new_value) {
         ST.input[posof[node]] = new_value;
         ST.update (0, 0, n - 1, posof[node], new_value);
     }
     int 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, ST.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, ST.query (0, 0, n - 1, posof[u], posof[v]));

        return answer;
     }
} HLD;

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);
   }

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

   for (int node = 0; node < n; node ++)
      ST.input[HLD.posof[node]] = cost[node];
   ST.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;
}