Cod sursa(job #2916386)

Utilizator andreic06Andrei Calota andreic06 Data 29 iulie 2022 16:02:42
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.98 kb
#include <bits/stdc++.h>

using namespace std;
const int INF = 2e9;
const int NMAX = 1e5;
const int LOG_MAX = 17;
const int ROOT = 1;
const int PARENT = 0;
const int NULL_COST = 0;


struct define_edge {
    int from, to;
    ///int cost;
}; vector<define_edge> tree[1 + NMAX];
int father[1 + NMAX], instant_cost[1 + NMAX];
int depth[1 + NMAX], size_of[1 + NMAX];
int n, q;

void dfs ( int p, int root ) {
   depth[root] = depth[p] + 1;
   father[root] = p;

   for ( auto edge : tree[root] ) {
      int child = edge.to;
      if ( child != p )
        dfs ( root, child );
   }

   size_of[root] = 1;
   for ( auto edge : tree[root] ) {
      int child = edge.to;
      if ( child != p )
        size_of[root] += size_of[child];
   }
}

int sgtree[1 + 4 * NMAX];
class SegTree {
   public :
      void update ( int node, int left, int right, int pos, int new_value );
      int query ( int node, int left, int right, int qleft, int qright );
      static inline int merge__ ( int first, int second );
} ST;

int SegTree :: merge__ ( int first, int second ) {
    return max ( first, second );
}
void SegTree :: update ( int node, int left, int right, int pos, int new_value ) {
   if ( left == right )
     sgtree[node] = new_value;
   else {
     int mid = left + (right - left) / 2;
     if ( pos <= mid )
       update ( node * 2, left, mid, pos, new_value );
     else
       update ( node * 2 + 1, mid + 1, right, pos, new_value );
     sgtree[node] = merge__ (sgtree[node * 2], sgtree[node * 2 + 1]);
   }
}
int SegTree :: query ( int node, int left, int right, int qleft, int qright ) {
   if ( qleft <= left && right <= qright )
     return sgtree[node];
   int mid = left + (right - left) / 2;

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

bool heavy[1 + NMAX]; /// muchia node-parinte este heavy
int b[1 + NMAX], e[1 + NMAX]; /// nodul de inceput si sfarsit al path-urilor
int chain_indx[1 + NMAX]; int k = 0; /// in ce path se afla nodul x
int pos[1 + NMAX]; /// pozitia in segtree a nodului x

class Heavy_Light_Decomposition  {
   public :
      void dfs_chain ( int p, int root );
      void construct_chain ();
      void update ( int node, int new_value );
      int query ( int u, int v );
} HLD;

void Heavy_Light_Decomposition :: dfs_chain ( int p, int root ) {
   for ( auto edge : tree[root] ) {
      int child = edge.to;
      if ( child != p ) {
        if ( size_of[child] > size_of[root] / 2 )
          heavy[child] = true;
        else
          heavy[child] = false;
        dfs_chain ( root, child );
      }
   }

   bool all_light = true;
   for ( auto edge : tree[root] ) {
      int child = edge.to;
      if ( child != p && heavy[child] == true )
        all_light = false;
   }
   if ( all_light == true )
     b[++ k] = root;
}
void Heavy_Light_Decomposition :: construct_chain () {
   int curr_pos = 0;
   for ( int indx = 1; indx <= k; indx ++ ) {
      int node = b[indx]; chain_indx[node] = indx;
      pos[node] = ++ curr_pos;
      while ( heavy[node] == true ) {
         node = father[node];
         chain_indx[node] = indx;
         pos[node] = ++ curr_pos;
      }
      e[indx] = node;
   }
}

void Heavy_Light_Decomposition :: update ( int node, int new_value ) {
   ST.update ( 1, 1, n, pos[node], new_value );
}
int Heavy_Light_Decomposition :: query ( int u, int v ) {
   if ( chain_indx[u] == chain_indx[v] ) {
     if ( pos[u] > pos[v] )
       swap ( u, v );
     return ST.query ( 1, 1, n, pos[u], pos[v] );
   }

   if ( depth[e[chain_indx[u]]] < depth[e[chain_indx[v]]] )
     swap ( u, v );
   int end_of_u = e[chain_indx[u]];
   return max ( ST.query ( 1, 1, n, pos[u], pos[end_of_u] ), query ( father[end_of_u], v ) );
}
int main()
{
   ifstream in ( "heavypath.in" );
   ofstream out ( "heavypath.out" );
   ios_base :: sync_with_stdio (false);
   in.tie (); out.tie ();


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

   dfs ( PARENT, ROOT );
   HLD.dfs_chain ( PARENT, ROOT ); HLD.construct_chain ();

   /**cout << k << "\n";
   for ( int indx = 1; indx <= n; indx ++ )
      cout << b[indx] << " " << e[indx] << "\n";**/

   for ( int node = 1; node <= n; node ++ )
      HLD.update ( node, instant_cost[node] );
   for ( int indx = 1; indx <= q; indx ++ ) {
      int task; in >> task;
      if ( task == 0 ) {
        int node, new_value; in >> node >> new_value;
        HLD.update ( node, new_value );
      }
      else {
        int u, v; in >> u >> v;
        out << HLD.query ( u, v ) << "\n";
      }
   }


    return 0;
}