Advertisement
_ash__

HLD on edges

Apr 13th, 2018
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.67 KB | None | 0 0
  1. #include <bits/stdtr1c++.h>
  2.  
  3. #define clr(ar) memset(ar, 0, sizeof(ar))
  4. #define read() freopen("lol.txt", "r", stdin)
  5. #define dbg(x) cout << #x << " = " << x << endl
  6.  
  7. #define NIL 0
  8. #define MAX 50010
  9. #define OPT(a, b) ((a)+(b))
  10. #define jump(x) ((num[x] == 0) ? -1 : down[up[x]])
  11.  
  12. using namespace std;
  13.  
  14. /// Heavy Light Decomposition on Trees, 0 based indices
  15. /// With RMQ support for edges
  16. /// Define the operation, default is +
  17. /// x * NIL = x, NIL = 0 for addition/subtraction, 1 for multiplication, INF/-INF for min/max, etc
  18. /// RMQ to add values on edges, if required to set/replace values modify appropriately
  19.  
  20. namespace hld{ /// hash = 163953
  21.     int r, n, id;
  22.     vector <int> adj[MAX], weight[MAX];
  23.     int nodeval[MAX], lazy[4 * MAX], tree[4 * MAX]; /// RMQ
  24.     int parent[MAX], children[MAX], height[MAX], num[MAX], up[MAX], down[MAX]; /// HLD
  25.  
  26.     /// num[i] = 0 if the edge from i to parent[i] is not heavy, otherwise num[i] = unique id of the heavy edge
  27.     /// down[i] = -1 if there is no heavy edge from i to it's children, otherwise down[i] = node number of the heavy child of i
  28.     /// up[i] = i, if i is root, otherwise up[i] = node number of parent of i following only heavy up edges and one last light edge
  29.  
  30.     void dfs(int i, int p){
  31.         parent[i] = p, children[i] = 1;
  32.         if (i != p) height[i] = height[p] + 1;
  33.  
  34.         int j, x, len = adj[i].size();
  35.         for (j = 0; j < len; j++){
  36.             x = adj[i][j];
  37.             if (x != p){
  38.                 dfs(x, i);
  39.                 nodeval[x] = weight[i][j];
  40.                 children[i] += children[x];
  41.             }
  42.         }
  43.     }
  44.  
  45.     /// build heavy light decomposition
  46.     void build(int i, int p){ /// hash = 989687
  47.         up[i] = i;
  48.         if (num[i]) up[i] = up[p];
  49.  
  50.         int j, x, h = -1, l = adj[i].size();
  51.         for (j = 0; j < l; j++){
  52.             x = adj[i][j];
  53.             if ((x != p) && ((children[x] << 1) >= children[i])) h = x;
  54.         }
  55.  
  56.         if (h != -1){
  57.             num[h] = ++id;
  58.             build(h, i);
  59.         }
  60.         for (j = 0, down[i] = h; j < l; j++){
  61.             x = adj[i][j];
  62.             if ((x != p) && (x != h)) build(x, i);
  63.         }
  64.     }
  65.  
  66.     void update_rmq(int idx, int a, int b, int l, int r, int x); /// RMQ update defined for build
  67.     void build(int root){
  68.         r = root, id = 0;
  69.         height[r] = 0, nodeval[r] = NIL;
  70.  
  71.         dfs(r, r);
  72.         build(r, r);
  73.         for (int i = 0; i < n; i++){
  74.             if (up[i] == i) up[i] = parent[i];
  75.         }
  76.  
  77.         /// Builds RMQ
  78.         clr(lazy);
  79.         for (int i = 0; i < (MAX << 2); i++) tree[i] = NIL;
  80.         for (int i = 0; i < n; i++){
  81.             if (num[i]) update_rmq(1, 1, id, num[i], num[i], nodeval[i]);
  82.         }
  83.     }
  84.     void build(){
  85.         build(0); /// Root set to 0 by default!
  86.     }
  87.  
  88.     int lca(int a, int b){
  89.         while (up[a] != up[b]){
  90.             if (height[up[a]] > height[up[b]]) a = up[a];
  91.             else b = up[b];
  92.         }
  93.  
  94.         if (a == b) return a;
  95.         if (num[a] && num[b]){
  96.             if (height[a] < height[b]) return a;
  97.             else return b;
  98.         }
  99.         return up[a];
  100.     }
  101.  
  102.     void add_edge(int a, int b, int w){
  103.         adj[a].push_back(b), weight[a].push_back(w);
  104.         adj[b].push_back(a), weight[b].push_back(w);
  105.     }
  106.  
  107.     void init(int nodes){
  108.         clr(num), n = nodes;
  109.         for (int i = 0; i < MAX; i++) adj[i].clear(), weight[i].clear();
  110.     }
  111.  
  112.     /************** RMQ functions **************/
  113.  
  114.  
  115.     /// Change lazy propagation accordingly
  116.     /// Note lazy and updates set for adding values in node, update if set/replace operation
  117.     inline void push(int idx, int a, int b){
  118.         int c = (a + b) >> 1, d = c + 1, p = idx << 1, q = p | 1;
  119.         if (lazy[idx]){
  120.             tree[idx] += (lazy[idx] * (b - a + 1)); /// Change lazy according to operation
  121.             if (a != b) lazy[p] += lazy[idx], lazy[q] += lazy[idx]; /// Change lazy according to operation
  122.             lazy[idx] = 0;
  123.         }
  124.     }
  125.  
  126.     /// Change query accordingly
  127.     int query_rmq(int idx, int a, int b, int l, int r){
  128.         int c = (a + b) >> 1, d = c + 1, p = idx << 1, q = p | 1;
  129.  
  130.         push(idx, a, b);
  131.         if (a == l && b == r) return tree[idx];
  132.         else if (r <= c) return query_rmq(p, a, c, l, r);
  133.         else if (l >= d) return query_rmq(q, d, b, l, r);
  134.         else return OPT(query_rmq(p, a, c, l, c), query_rmq(q, d, b, d, r));
  135.     }
  136.  
  137.     /// Change update accordingly
  138.     void update_rmq(int idx, int a, int b, int l, int r, int x){ /// hash = 487503
  139.         int p = (idx << 1), q = p + 1, c = (a + b) >> 1, d = c + 1;
  140.  
  141.         if (a == l && b == r) lazy[idx] += x; /// Change lazy according to operation, change here if set
  142.         push(idx, a, b);
  143.         if (a == l && b == r) return;
  144.  
  145.         if (r <= c){
  146.             push(q, d, b);
  147.             update_rmq(p, a, c, l, r, x);
  148.         }
  149.         else if (l >= d){
  150.             push(p, a, c);
  151.             update_rmq(q, d, b, l, r, x);
  152.         }
  153.         else{
  154.             update_rmq(p, a, c, l, c, x);
  155.             update_rmq(q, d, b, d, r, x);
  156.         }
  157.  
  158.         tree[idx] = OPT(tree[p], tree[q]);
  159.     }
  160.  
  161.     /************** HLD + RMQ **************/
  162.  
  163.     /// Sum of all edges in the path from u to l, l must be an ancestor of u
  164.     int query_tree(int u, int l){ /// hash = 486879
  165.         int res = NIL;
  166.         while (height[u] > height[l]){
  167.             if (num[u]){
  168.                 int v = jump(u);
  169.                 if (height[v] <= height[l]) v = down[l];
  170.                 res = OPT(res, query_rmq(1, 1, id, num[v], num[u]));
  171.                 u = parent[v];
  172.             }
  173.             else res = OPT(nodeval[u], res), u = parent[u];
  174.         }
  175.         return res;
  176.     }
  177.  
  178.     /// Sum of all edges in the path from u to v
  179.     int query(int u, int v){
  180.         int l = lca(u, v), res = NIL;
  181.         res = OPT(res, query_tree(u, l));
  182.         res = OPT(res, query_tree(v, l));
  183.         return res;
  184.     }
  185.  
  186.     /// Add w to all edges in the path from u to l, l must be an ancestor of u
  187.     void update_tree(int u, int l, int w){
  188.         while (height[u] > height[l]){
  189.             if (num[u]){
  190.                 int v = jump(u);
  191.                 if (height[v] <= height[l]) v = down[l];
  192.                 update_rmq(1, 1, id, num[v], num[u], w);
  193.                 u = parent[v];
  194.             }
  195.             else nodeval[u] = OPT(nodeval[u], w), u = parent[u]; /// Change here if set instead of add
  196.         }
  197.     }
  198.  
  199.     /// Add w to all edges in the path from u to v
  200.     void update(int u, int v, int w){
  201.         int l = lca(u, v);
  202.         update_tree(u, l, w);
  203.         update_tree(v, l, w);
  204.     }
  205. }
  206.  
  207. int main(){
  208.  
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement