BotByte

HLD temp.cpp

Apr 20th, 2018
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.61 KB | None | 0 0
  1. #include <cstdio>
  2. #include <vector>
  3. using namespace std;
  4.  
  5. #define root 0
  6. #define N 10100
  7. #define LN 14
  8.  
  9. vector <int> adj[N], costs[N], indexx[N];
  10. int baseArray[N], ptr;
  11. int chainNo, chainInd[N], chainHead[N], posInBase[N];
  12. int depth[N], pa[LN][N], otherEnd[N], subsize[N];
  13. int st[N*6], qt[N*6];
  14.  
  15. /*
  16.  * make_tree:
  17.  * Used to construct the segment tree. It uses the baseArray for construction
  18.  */
  19. void make_tree(int cur, int s, int e) {
  20.     if(s == e-1) {
  21.         st[cur] = baseArray[s];
  22.         return;
  23.     }
  24.     int c1 = (cur<<1), c2 = c1 | 1, m = (s+e)>>1;
  25.     make_tree(c1, s, m);
  26.     make_tree(c2, m, e);
  27.     st[cur] = st[c1] > st[c2] ? st[c1] : st[c2];
  28. }
  29.  
  30. /*
  31.  * update_tree:
  32.  * Point update. Update a single element of the segment tree.
  33.  */
  34. void update_tree(int cur, int s, int e, int x, int val) {
  35.     if(s > x || e <= x) return;
  36.     if(s == x && s == e-1) {
  37.         st[cur] = val;
  38.         return;
  39.     }
  40.     int c1 = (cur<<1), c2 = c1 | 1, m = (s+e)>>1;
  41.     update_tree(c1, s, m, x, val);
  42.     update_tree(c2, m, e, x, val);
  43.     st[cur] = st[c1] > st[c2] ? st[c1] : st[c2];
  44. }
  45.  
  46. /*
  47.  * query_tree:
  48.  * Given S and E, it will return the maximum value in the range [S,E)
  49.  */
  50. void query_tree(int cur, int s, int e, int S, int E) {
  51.     if(s >= E || e <= S) {
  52.         qt[cur] = -1;
  53.         return;
  54.     }
  55.     if(s >= S && e <= E) {
  56.         qt[cur] = st[cur];
  57.         return;
  58.     }
  59.     int c1 = (cur<<1), c2 = c1 | 1, m = (s+e)>>1;
  60.     query_tree(c1, s, m, S, E);
  61.     query_tree(c2, m, e, S, E);
  62.     qt[cur] = qt[c1] > qt[c2] ? qt[c1] : qt[c2];
  63. }
  64.  
  65. /*
  66.  * query_up:
  67.  * It takes two nodes u and v, condition is that v is an ancestor of u
  68.  * We query the chain in which u is present till chain head, then move to next chain up
  69.  * We do that way till u and v are in the same chain, we query for that part of chain and break
  70.  */
  71.  
  72. int query_up(int u, int v) {
  73.     if(u == v) return 0; // Trivial
  74.     int uchain, vchain = chainInd[v], ans = -1;
  75.     // uchain and vchain are chain numbers of u and v
  76.     while(1) {
  77.         uchain = chainInd[u];
  78.         if(uchain == vchain) {
  79.             // Both u and v are in the same chain, so we need to query from u to v, update answer and break.
  80.             // We break because we came from u up till v, we are done
  81.             if(u==v) break;
  82.             query_tree(1, 0, ptr, posInBase[v]+1, posInBase[u]+1);
  83.             // Above is call to segment tree query function
  84.             if(qt[1] > ans) ans = qt[1]; // Update answer
  85.             break;
  86.         }
  87.         query_tree(1, 0, ptr, posInBase[chainHead[uchain]], posInBase[u]+1);
  88.         // Above is call to segment tree query function. We do from chainHead of u till u. That is the whole chain from
  89.         // start till head. We then update the answer
  90.         if(qt[1] > ans) ans = qt[1];
  91.         u = chainHead[uchain]; // move u to u's chainHead
  92.         u = pa[0][u]; //Then move to its parent, that means we changed chains
  93.     }
  94.     return ans;
  95. }
  96.  
  97. /*
  98.  * LCA:
  99.  * Takes two nodes u, v and returns Lowest Common Ancestor of u, v
  100.  */
  101. int LCA(int u, int v) {
  102.     if(depth[u] < depth[v]) swap(u,v);
  103.     int diff = depth[u] - depth[v];
  104.     for(int i=0; i<LN; i++) if( (diff>>i)&1 ) u = pa[i][u];
  105.     if(u == v) return u;
  106.     for(int i=LN-1; i>=0; i--) if(pa[i][u] != pa[i][v]) {
  107.         u = pa[i][u];
  108.         v = pa[i][v];
  109.     }
  110.     return pa[0][u];
  111. }
  112.  
  113. void query(int u, int v) {
  114.     /*
  115.      * We have a query from u to v, we break it into two queries, u to LCA(u,v) and LCA(u,v) to v
  116.      */
  117.     int lca = LCA(u, v);
  118.     int ans = query_up(u, lca); // One part of path
  119.     int temp = query_up(v, lca); // another part of path
  120.     if(temp > ans) ans = temp; // take the maximum of both paths
  121.     printf("%d\n", ans);
  122. }
  123.  
  124. /*
  125.  * change:
  126.  * We just need to find its position in segment tree and update it
  127.  */
  128. void change(int i, int val) {
  129.     int u = otherEnd[i];
  130.     update_tree(1, 0, ptr, posInBase[u], val);
  131. }
  132.  
  133. /*
  134.  * Actual HL-Decomposition part
  135.  * Initially all entries of chainHead[] are set to -1.
  136.  * So when ever a new chain is started, chain head is correctly assigned.
  137.  * As we add a new node to chain, we will note its position in the baseArray.
  138.  * In the first for loop we find the child node which has maximum sub-tree size.
  139.  * The following if condition is failed for leaf nodes.
  140.  * When the if condition passes, we expand the chain to special child.
  141.  * In the second for loop we recursively call the function on all normal nodes.
  142.  * chainNo++ ensures that we are creating a new chain for each normal child.
  143.  */
  144. void HLD(int curNode, int cost, int prev) {
  145.     if(chainHead[chainNo] == -1) {
  146.         chainHead[chainNo] = curNode; // Assign chain head
  147.     }
  148.     chainInd[curNode] = chainNo;
  149.     posInBase[curNode] = ptr; // Position of this node in baseArray which we will use in Segtree
  150.     baseArray[ptr++] = cost;
  151.  
  152.     int sc = -1, ncost;
  153.     // Loop to find special child
  154.     for(int i=0; i<adj[curNode].size(); i++) if(adj[curNode][i] != prev) {
  155.         if(sc == -1 || subsize[sc] < subsize[adj[curNode][i]]) {
  156.             sc = adj[curNode][i];
  157.             ncost = costs[curNode][i];
  158.         }
  159.     }
  160.  
  161.     if(sc != -1) {
  162.         // Expand the chain
  163.         HLD(sc, ncost, curNode);
  164.     }
  165.  
  166.     for(int i=0; i<adj[curNode].size(); i++) if(adj[curNode][i] != prev) {
  167.         if(sc != adj[curNode][i]) {
  168.             // New chains at each normal node
  169.             chainNo++;
  170.             HLD(adj[curNode][i], costs[curNode][i], curNode);
  171.         }
  172.     }
  173. }
  174.  
  175. /*
  176.  * dfs used to set parent of a node, depth of a node, subtree size of a node
  177.  */
  178. void dfs(int cur, int prev, int _depth=0) {
  179.     pa[0][cur] = prev;
  180.     depth[cur] = _depth;
  181.     subsize[cur] = 1;
  182.     for(int i=0; i<adj[cur].size(); i++)
  183.         if(adj[cur][i] != prev) {
  184.             otherEnd[indexx[cur][i]] = adj[cur][i];
  185.             dfs(adj[cur][i], cur, _depth+1);
  186.             subsize[cur] += subsize[adj[cur][i]];
  187.         }
  188. }
  189.  
  190. int main() {
  191.     int t;
  192.     scanf("%d ", &t);
  193.     while(t--) {
  194.         ptr = 0;
  195.         int n;
  196.         scanf("%d", &n);
  197.         // Cleaning step, new test case
  198.         for(int i=0; i<n; i++) {
  199.             adj[i].clear();
  200.             costs[i].clear();
  201.             indexx[i].clear();
  202.             chainHead[i] = -1;
  203.             for(int j=0; j<LN; j++) pa[j][i] = -1;
  204.         }
  205.         for(int i=1; i<n; i++) {
  206.             int u, v, c;
  207.             scanf("%d %d %d", &u, &v, &c);
  208.             u--; v--;
  209.             adj[u].push_back(v);
  210.             costs[u].push_back(c);
  211.             indexx[u].push_back(i-1);
  212.             adj[v].push_back(u);
  213.             costs[v].push_back(c);
  214.             indexx[v].push_back(i-1);
  215.         }
  216.  
  217.         chainNo = 0;
  218.         dfs(root, -1); // We set up subsize, depth and parent for each node
  219.         HLD(root, -1, -1); // We decomposed the tree and created baseArray
  220.         make_tree(1, 0, ptr); // We use baseArray and construct the needed segment tree
  221.  
  222.         // Below Dynamic programming code is for LCA.
  223.         for(int i=1; i<LN; i++)
  224.             for(int j=0; j<n; j++)
  225.                 if(pa[i-1][j] != -1)
  226.                     pa[i][j] = pa[i-1][pa[i-1][j]];
  227.  
  228.         while(1) {
  229.             char s[100];
  230.             scanf("%s", s);
  231.             if(s[0]=='D') {
  232.                 break;
  233.             }
  234.             int a, b;
  235.             scanf("%d %d", &a, &b);
  236.             if(s[0]=='Q') {
  237.                 query(a-1, b-1);
  238.             } else {
  239.                 change(a-1, b);
  240.             }
  241.         }
  242.     }
  243. }
Advertisement
Add Comment
Please, Sign In to add comment