Saturday, February 2, 2019

[UVA] 13101 - Tobby on Tree

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : 13101 - Tobby on Tree
Source            : UVA Online Judge
Category          : Graph Theory
Algorithm         : Heavy Light Decomposition, Segment Tree
Verdict           : Accepted

  1. #include <bits/stdc++.h>  
  2.   
  3. using namespace std;  
  4.   
  5.   
  6. static const int maxn = 1e5 + 5;  
  7. static const int logn = 18;  
  8.   
  9. int chainNo, chainHead[maxn], chainInd[maxn], chainPos[maxn], chainSize[maxn],  
  10.     baseArray[maxn], posBase[maxn], ptr,  
  11.     depth[maxn], father[maxn][logn], subTreeSize[maxn], starttnode[maxn], endtnode[maxn],  
  12.     S, E, nodeCost[maxn];  
  13.   
  14. vector <int> graph[maxn];  
  15.   
  16. void dfs(int u = 1, int p = -1)  
  17. {  
  18.       for (int i = 1; i < logn; i++) father[u][i] = father[ father[u][i-1] ][i-1];  
  19.       subTreeSize[u] = 1;  
  20.       for (int v : graph[u])  
  21.       {  
  22.             if (v == p) continue;  
  23.             depth[v] = depth[u] + 1;  
  24.             father[v][0] = u;  
  25.             dfs(v, u);  
  26.             subTreeSize[u] += subTreeSize[v];  
  27.       }  
  28. }  
  29.   
  30. int findLCA(int u, int v)  
  31. {  
  32.       if (depth[u] < depth[v]) swap(u, v);  
  33.       for (int i = logn-1; i >= 0; i--)  
  34.       {  
  35.             if (depth[ father[u][i] ] >= depth[v])  
  36.             {  
  37.                   u = father[u][i];  
  38.             }  
  39.       }  
  40.       if (u == v) return u;  
  41.       for (int i = logn-1; i >= 0; i--)  
  42.       {  
  43.             if (father[u][i] != father[v][i])  
  44.             {  
  45.                   u = father[u][i];  
  46.                   v = father[v][i];  
  47.             }  
  48.       }  
  49.       return father[u][0];  
  50. }  
  51.   
  52. void hld(int u = 1, int p = -1)  
  53. {  
  54.       if (chainHead[chainNo] == -1) chainHead[chainNo] = u;  
  55.       chainInd[u] = chainNo;  
  56.       ptr++;  
  57.       baseArray[ptr] = nodeCost[u];  
  58.       posBase[u] = ptr;  
  59.       int bigChild(-1), mx(-1);  
  60.       for (int v : graph[u])  
  61.       {  
  62.             if (v == p) continue;  
  63.             if (subTreeSize[v] > mx) mx = subTreeSize[v], bigChild = v;  
  64.       }  
  65.       if (bigChild != -1) hld(bigChild, u);  
  66.       for (int v : graph[u])  
  67.       {  
  68.             if (v == p) continue;  
  69.             if (bigChild != v)  
  70.             {  
  71.                   chainNo++;  
  72.                   hld(v, u);  
  73.             }  
  74.       }  
  75. }  
  76.   
  77. int Tree[maxn << 2];  
  78.   
  79. void build(int node, int a, int b)  
  80. {  
  81.       if (a == b)  
  82.       {  
  83.             Tree[node] = baseArray[a];  
  84.             return;  
  85.       }  
  86.       int lft = node << 1;  
  87.       int rgt = lft | 1;  
  88.       int mid = (a + b) >> 1;  
  89.       build(lft, a, mid);  
  90.       build(rgt, mid+1, b);  
  91.       Tree[node] = __gcd(Tree[lft], Tree[rgt]);  
  92. }  
  93.   
  94. void update(int node, int a, int b, int pos, int val)  
  95. {  
  96.       if (a > b || a > pos || b < pos) return;  
  97.       if (a >= pos && b <= pos)  
  98.       {  
  99.             Tree[node] = val;  
  100.             return;  
  101.       }  
  102.       int lft = node << 1;  
  103.       int rgt = lft | 1;  
  104.       int mid = (a + b) >> 1;  
  105.       update(lft, a, mid, pos, val);  
  106.       update(rgt, mid+1, b, pos, val);  
  107.       Tree[node] = __gcd(Tree[lft], Tree[rgt]);  
  108. }  
  109.   
  110. int query(int node, int a, int b, int i, int j)  
  111. {  
  112.       if (a > b || a > j || b < i) return 0;  
  113.       if (a >= i && b <= j) return Tree[node];  
  114.       int lft = node << 1;  
  115.       int rgt = lft | 1;  
  116.       int mid = (a + b) >> 1;  
  117.       int p1 = query(lft, a, mid, i, j);  
  118.       int p2 = query(rgt, mid+1, b, i, j);  
  119.       return __gcd(p1, p2);  
  120. }  
  121.   
  122. int query_up(int u, int v)  
  123. {  
  124.       // u niche, v upore  
  125.       int uChain, vChain = chainInd[v];  
  126.       int g = 0;  
  127.       while (true)  
  128.       {  
  129.             uChain = chainInd[u];  
  130.             if (uChain == vChain)  
  131.             {  
  132.                   int l = posBase[v];  
  133.                   int r = posBase[u];  
  134.                   if (l > r) break;  
  135.                   int ans = query(1, S, E, l, r);  
  136.                   g = __gcd(g, ans);  
  137.                   break;  
  138.             }  
  139.             int l = posBase[ chainHead[uChain] ];  
  140.             int r = posBase[u];  
  141.             int ans = query(1, S, E, l, r);  
  142.             g = __gcd(g, ans);  
  143.             u = father[ chainHead[uChain] ][0];  
  144.       }  
  145.       return g;  
  146. }  
  147.   
  148. int query_hld(int u, int v)  
  149. {  
  150.       int lca = findLCA(u, v);  
  151.       int ans = 0;  
  152.       ans = __gcd(ans, query_up(u, lca));  
  153.       ans = __gcd(ans, query_up(v, lca));  
  154.       return ans;  
  155. }  
  156.   
  157. void change_node_cost(int u, int val)  
  158. {  
  159.       int pos = posBase[u];  
  160.       nodeCost[u] = val;  
  161.       update(1, S, E, pos, val);  
  162. }  
  163.   
  164. void init()  
  165. {  
  166.       ptr = 0;  
  167.       chainNo = 0;  
  168.       for (int i = 0; i < maxn; i++)  
  169.       {  
  170.             graph[i].clear();  
  171.             subTreeSize[i] = 0;  
  172.             chainHead[i] = -1;  
  173.             depth[i] = 0;  
  174.             baseArray[i] = 0;  
  175.             posBase[i] = 0;  
  176.             fill(begin(father[i]), end(father[i]), 0);  
  177.       }  
  178. }  
  179.   
  180. int main()  
  181.       int tnode;  
  182.       while (scanf("%d", &tnode) == 1)  
  183.       {  
  184.             init();  
  185.             for (int i = 1; i <= tnode; i++) scanf("%d", nodeCost+i);  
  186.             for (int e = 1; e < tnode; e++)  
  187.             {  
  188.                   int u, v;  
  189.                   scanf("%d %d", &u, &v);  
  190.                   u++; v++;  
  191.                   graph[u].push_back(v);  
  192.                   graph[v].push_back(u);  
  193.             }  
  194.             depth[1] = 1;  
  195.             dfs();  
  196.             hld();  
  197.             S = 1;  
  198.             E = ptr;  
  199.             build(1, S, E);  
  200.             int tquery;  
  201.             scanf("%d", &tquery);  
  202.             while (tquery--)  
  203.             {  
  204.                   int type;  
  205.                   scanf("%d", &type);  
  206.                   if (type == 1)  
  207.                   {  
  208.                         int u, v;  
  209.                         scanf("%d %d", &u, &v);  
  210.                         u++; v++;  
  211.                         int ans = query_hld(u, v);  
  212.                         printf("%d\n", ans);  
  213.                   }  
  214.                   else  
  215.                   {  
  216.                         int u, x;  
  217.                         scanf("%d %d", &u, &x);  
  218.                         u++;  
  219.                         change_node_cost(u, x);  
  220.                   }  
  221.             }  
  222.       }  
  223. }  

No comments:

Post a Comment

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