Tuesday, January 8, 2019

[Gym] Subway Lines

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Subway Lines
Source            : Gym
Category          : Data Structure, Graph Theory, Tree
Algorithm         : Heavy Light Decomposition, Segment Tree, Lazy Propagation
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.    
  3. using namespace std;  
  4.    
  5. static const int maxn = 1e5 + 5;  
  6. static const int logn = 18;  
  7.    
  8. vector <int> graph[maxn];  
  9. int depth[maxn];  
  10. int father[maxn][logn];  
  11. int subtreeSize[maxn];  
  12.    
  13. int N;  
  14.    
  15. inline void dfs(int u = 1, int p = -1)  
  16. {  
  17.       for (int i = 1; i < logn; i++)  
  18.       {  
  19.             father[u][i] = father[ father[u][i-1] ][i-1];  
  20.       }  
  21.       subtreeSize[u] = 1;  
  22.       for (int v : graph[u])  
  23.       {  
  24.             if (v == p) continue;  
  25.             depth[v] = depth[u] + 1;  
  26.             father[v][0] = u;  
  27.             dfs(v, u);  
  28.             subtreeSize[u] += subtreeSize[v];  
  29.       }  
  30. }  
  31.    
  32. inline int findLCA(int u, int v)  
  33. {  
  34.       if (depth[u] < depth[v]) swap(u, v);  
  35.       for (int i = logn-1; i >= 0; i--)  
  36.       {  
  37.             if (depth[ father[u][i] ] >= depth[v])  
  38.             {  
  39.                   u = father[u][i];  
  40.             }  
  41.       }  
  42.       if (u == v) return u;  
  43.       for (int i = logn-1; i >= 0; i--)  
  44.       {  
  45.             if (father[u][i] != father[v][i])  
  46.             {  
  47.                   u = father[u][i];  
  48.                   v = father[v][i];  
  49.             }  
  50.       }  
  51.       return father[v][0];  
  52. }  
  53.    
  54.    
  55. int chainNo,  
  56.     chainHead[maxn],  
  57.     chainInd[maxn],  
  58.     chainPos[maxn],  
  59.     baseArray[maxn],  
  60.     posBase[maxn],  
  61.     ptr;  
  62.    
  63. struct segmentTree  
  64. {  
  65.       int sum, lazy;  
  66.       segmentTree(int sum = 0, int lazy = -1) :  
  67.             sum(sum), lazy(lazy) {}  
  68. } Tree[maxn << 2];  
  69.    
  70. inline void updateLazy(int node, int a, int b, int val)  
  71. {  
  72.       Tree[node].sum = (b - a + 1) * val;  
  73.       Tree[node].lazy = val;  
  74. }  
  75.    
  76. inline void updateNode(int node, int a, int b)  
  77. {  
  78.       int lft = node << 1;  
  79.       int rgt = lft | 1;  
  80.       int mid = (a + b) >> 1;  
  81.       Tree[lft].sum = (mid - a + 1) * Tree[node].lazy;  
  82.       Tree[rgt].sum = (b - mid) * Tree[node].lazy;  
  83.       Tree[lft].lazy = Tree[rgt].lazy = Tree[node].lazy;  
  84.    
  85.       Tree[node].lazy = -1;  
  86. }  
  87.    
  88. inline void update(int node, int a, int b, int i, int j, int val)  
  89. {  
  90.       if (a == i && b == j)  
  91.       {  
  92.             updateLazy(node, a, b, val);  
  93.             return;  
  94.       }  
  95.       if (Tree[node].lazy != -1)  
  96.       {  
  97.             updateNode(node, a, b);  
  98.       }  
  99.       int lft = node << 1;  
  100.       int rgt = lft | 1;  
  101.       int mid = (a + b) >> 1;  
  102.       if (j <= mid)  
  103.       {  
  104.             update(lft, a, mid, i, j, val);  
  105.       }  
  106.       else if (i > mid)  
  107.       {  
  108.             update(rgt, mid+1, b, i, j, val);  
  109.       }  
  110.       else  
  111.       {  
  112.             update(lft, a, mid, i, mid, val);  
  113.             update(rgt, mid+1, b, mid+1, j, val);  
  114.       }  
  115.       Tree[node].sum = Tree[lft].sum + Tree[rgt].sum;  
  116. }  
  117.    
  118. inline int query(int node, int a, int b, int i, int j)  
  119. {  
  120.       if (a == i && b == j) return Tree[node].sum;  
  121.       if (Tree[node].lazy != -1)  
  122.       {  
  123.             updateNode(node, a, b);  
  124.       }  
  125.       int lft = node << 1;  
  126.       int rgt = lft | 1;  
  127.       int mid = (a + b) >> 1;  
  128.       int sum = 0;  
  129.       if (j <= mid)  
  130.       {  
  131.             sum += query(lft, a, mid, i, j);  
  132.       }  
  133.       else if (i > mid)  
  134.       {  
  135.             sum += query(rgt, mid+1, b, i, j);  
  136.       }  
  137.       else  
  138.       {  
  139.             sum += query(lft, a, mid, i, mid);  
  140.             sum += query(rgt, mid+1, b, mid+1, j);  
  141.       }  
  142.       Tree[node].sum = Tree[lft].sum + Tree[rgt].sum;  
  143.       return sum;  
  144. }  
  145.    
  146. inline void hld(int u = 1, int p = -1)  
  147. {  
  148.       if (chainHead[chainNo] == -1) chainHead[chainNo] = u;  
  149.       chainInd[u] = chainNo;  
  150.       ptr++;  
  151.       baseArray[ptr] = u;  
  152.       posBase[u] = ptr;  
  153.       int mx = -1, bigChild = -1;  
  154.       for (int v : graph[u])  
  155.       {  
  156.             if (v == p) continue;  
  157.             if (subtreeSize[v] > mx) mx = subtreeSize[v], bigChild = v;  
  158.       }  
  159.       if (bigChild != -1) hld(bigChild, u);  
  160.       for (int v : graph[u])  
  161.       {  
  162.             if (v == p or bigChild == v) continue;  
  163.             chainNo++;  
  164.             hld(v, u);  
  165.       }  
  166. }  
  167.    
  168. inline void update_path(int u, int v)  
  169. {  
  170.       int uChain, vChain = chainInd[v];  
  171.       while (true)  
  172.       {  
  173.             uChain = chainInd[u];  
  174.             if (uChain == vChain)  
  175.             {  
  176.                   int l = posBase[v];  
  177.                   int r = posBase[u];  
  178.                   if (l > r) break;  
  179.                   update(1, 1, N, l, r, 1);  
  180.                   break;  
  181.             }  
  182.             int l = posBase[ chainHead[uChain] ];  
  183.             int r = posBase[u];  
  184.             assert(l <= r);  
  185.             update(1, 1, N, l, r, 1);  
  186.             u = father[ chainHead[uChain] ][0];  
  187.       }  
  188. }  
  189.    
  190. inline void update_lca(int u, int v)  
  191. {  
  192.       int lca = findLCA(u, v);  
  193.       update_path(u, lca);  
  194.       update_path(v, lca);  
  195. }  
  196.    
  197. inline int query_path(int u, int v)  
  198. {  
  199.       int uChain;  
  200.       int vChain = chainInd[v];  
  201.       int sum = 0;  
  202.       while (true)  
  203.       {  
  204.             uChain = chainInd[u];  
  205.             if (uChain == vChain)  
  206.             {  
  207.                   int l = posBase[v];  
  208.                   int r = posBase[u];  
  209.                   if (l > r) break;  
  210.                   sum += query(1, 1, N, l, r);  
  211.                   break;  
  212.             }  
  213.             int l = posBase[ chainHead[uChain] ];  
  214.             int r = posBase[u];  
  215.             assert(l <= r);  
  216.             sum += query(1, 1, N, l, r);  
  217.             u = father[ chainHead[uChain] ][0];  
  218.       }  
  219.       return sum;  
  220. }  
  221.    
  222. inline int query_lca(int u, int v)  
  223. {  
  224.       int lca = findLCA(u, v);  
  225.       int sum1 = query_path(u, lca);  
  226.       int sum2 = query_path(v, lca);  
  227.       int sumlca = query_path(lca, lca);  
  228.       int sum = sum1 + sum2 - sumlca;  
  229.       return sum;  
  230. }  
  231.    
  232. inline void init()  
  233. {  
  234.       ptr = 0;  
  235.       chainNo = 0;  
  236.       for (int i = 0; i < maxn; i++)  
  237.       {  
  238.             graph[i].clear();  
  239.             subtreeSize[i] = 0;  
  240.             depth[i] = 0;  
  241.             baseArray[i] = 0;  
  242.             posBase[i] = 0;  
  243.             chainInd[i] = 0;  
  244.             chainHead[i] = -1;  
  245.             for (int j = 0; j < logn; j++) father[i][j] = 0;  
  246.       }  
  247. }  
  248.    
  249. int main()  
  250. {  
  251.       freopen("in.txt""r", stdin);  
  252.    
  253.       init();  
  254.       int tnode, tquery;  
  255.       scanf("%d %d", &tnode, &tquery);  
  256.       for (int i = 1; i < tnode; i++)  
  257.       {  
  258.             int u, v;  
  259.             scanf("%d %d", &u, &v);  
  260.             graph[u].emplace_back(v);  
  261.             graph[v].emplace_back(u);  
  262.       }  
  263.       N = tnode;  
  264.       depth[1] = 1;  
  265.       dfs();  
  266.       hld();  
  267.       while (tquery--)  
  268.       {  
  269.             int a, b, c, d;  
  270.             scanf("%d %d %d %d", &a, &b, &c, &d);  
  271.             update(1, 1, N, 1, N, 0);  
  272.             update_lca(a, b);  
  273.             int ans = query_lca(c, d);  
  274.             printf("%d\n", ans);  
  275.       }  
  276. }  

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.