Tarango

Codechef Dynamic GCD

Sep 15th, 2015
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.17 KB | None | 0 0
  1. //============================================================================
  2. // Name        : ACM
  3. // Author      : Tarango Khan
  4. // Team        : BRACU Byteheads
  5. //============================================================================
  6.  
  7. #include <bits/stdc++.h>
  8. using namespace std;
  9.  
  10. /*-------------------------Main code begins now ------------------------------*/
  11. int testnum;
  12. struct LCA {
  13. #include <vector>
  14.  
  15.     vector<int> L, D;
  16.     vector<vector<int> > P;
  17.     int N;
  18.     LCA(vector<int> dad, vector<int> level) {
  19.         N = dad.size();
  20.         D = dad, L = level;
  21.         int LOG = 1, base = 1;
  22.  
  23.         while (base < N)
  24.             LOG++, base <<= 1;
  25.  
  26.         P.resize(N, vector<int>(LOG, -1));
  27.  
  28.         for (int i = 0; i < N; i++)
  29.             P[i][0] = D[i];
  30.  
  31.         for (int j = 1; 1 << j < N; j++)
  32.             for (int i = 0; i < N; i++)
  33.                 if (P[i][j - 1] != -1)
  34.                     P[i][j] = P[P[i][j - 1]][j - 1];
  35.     }
  36.  
  37.     int query(int p, int q) {
  38.         int tmp, log, i;
  39.         if (L[p] < L[q])
  40.             tmp = p, p = q, q = tmp;
  41.  
  42.         for (log = 1; 1 << log <= L[p]; log++)
  43.             ;
  44.         log--;
  45.  
  46.         for (i = log; i >= 0; i--)
  47.             if (L[p] - (1 << i) >= L[q])
  48.                 p = P[p][i];
  49.  
  50.         if (p == q)
  51.             return p;
  52.  
  53.         for (i = log; i >= 0; i--)
  54.             if (P[p][i] != -1 && P[p][i] != P[q][i])
  55.                 p = P[p][i], q = P[q][i];
  56.  
  57.         return D[p];
  58.     }
  59. };
  60.  
  61. int gcd(int a, int b) {
  62.     if (b == 0)
  63.         return a;
  64.     return gcd(b, a % b);
  65. }
  66.  
  67. struct segment {
  68.     int first, last, diffGcd;
  69.     int lazysum;
  70. };
  71.  
  72. void addSegment(segment &s1, segment &s2, segment &s3) {
  73.     s3.first = s1.first;
  74.     s3.last = s2.last;
  75.     s3.diffGcd = abs(gcd(s1.diffGcd, gcd(s2.first - s1.last, s2.diffGcd)));
  76. }
  77. void getSegment(int a, segment &s) {
  78.     s.first = s.last = a;
  79.     s.lazysum = 0;
  80.     s.diffGcd = 0;
  81. }
  82.  
  83. struct segtree {
  84.     int base;
  85.     vector<segment> tree;
  86.     vector<int> A;
  87.  
  88.     segtree(vector<int> _A) {
  89.         A = _A;
  90.         int N = A.size();
  91.         base = 1;
  92.         while (base < N)
  93.             base *= 2;
  94.         tree.resize(2 * base);
  95.         makeSegment(1);
  96.     }
  97.  
  98.     void makeSegment(int ind) {
  99.         if (ind >= base)
  100.             getSegment(A[ind - base], tree[ind]);
  101.         else {
  102.             int twice = ind << 1;
  103.             makeSegment(twice);
  104.             makeSegment(twice + 1);
  105.             addSegment(tree[twice], tree[twice + 1], tree[ind]);
  106.             tree[ind].lazysum = 0;
  107.         }
  108.     }
  109.  
  110.     int lo, hi;
  111.  
  112.     void update(int ind, int beg, int end, int d) {
  113.         if (end < lo || beg > hi)
  114.             return;
  115.         if (lo <= beg && end <= hi) {
  116.             tree[ind].first += d;
  117.             tree[ind].last += d;
  118.             tree[ind].lazysum += d;
  119.             return;
  120.         }
  121.         int twice = ind << 1, mid = (beg + end) >> 1;
  122.  
  123.         update(twice, beg, mid, d);
  124.         update(twice + 1, mid + 1, end, d);
  125.  
  126.         addSegment(tree[twice], tree[twice + 1], tree[ind]);
  127.         tree[ind].first += tree[ind].lazysum;
  128.         tree[ind].last += tree[ind].lazysum;
  129.     }
  130.  
  131.     int query(int ind, int beg, int end, int lazysum) {
  132.         if (end < lo || beg > hi)
  133.             return 0;
  134.         if (lo <= beg && end <= hi)
  135.             return gcd(tree[ind].first + lazysum, tree[ind].diffGcd);
  136.  
  137.         lazysum += tree[ind].lazysum;
  138.         int twice = ind << 1, mid = (beg + end) >> 1;
  139.  
  140.         return gcd(query(twice, beg, mid, lazysum),
  141.                 query(twice + 1, mid + 1, end, lazysum));
  142.     }
  143.  
  144.     void update(int u, int v, int d) {
  145.         lo = u, hi = v;
  146.         update(1, 0, base - 1, d);
  147.     }
  148.  
  149.     int query(int u, int v) {
  150.         lo = u, hi = v;
  151.         return query(1, 0, base - 1, 0);
  152.     }
  153. };
  154.  
  155. /*****************************************************************/
  156. const int maxn = 100005;
  157. vector<int> Graph[maxn];
  158. int dad[maxn], subSize[maxn], level[maxn];
  159. int N;
  160.  
  161. int dfs(int u, int p, int l) {
  162.     if (dad[u] >= 0)
  163.         return 0;
  164.     dad[u] = p;
  165.     level[u] = l;
  166.  
  167.     int its = 0;
  168.     for (vector<int>::iterator it = Graph[u].begin(); it != Graph[u].end();
  169.             it++) {
  170.         its += dfs(*it, u, l + 1);
  171.     }
  172.     return subSize[u] = 1 + its;
  173. }
  174.  
  175. int chainNo;
  176. vector<int> chain[maxn];
  177. int chainHead[maxn], chainPos[maxn], chainIndex[maxn];
  178. int A[maxn];
  179.  
  180. void HLD(int u) {
  181.     if (chain[chainNo].size() == 0){
  182.         chainHead[chainNo] = u;
  183.     }
  184.  
  185.     chain[chainNo].push_back(u);
  186.     chainPos[u] = chain[chainNo].size() - 1;
  187.     chainIndex[u] = chainNo;
  188.  
  189.     int most = 0, ind = -1;
  190.  
  191.     for (vector<int>::iterator it = Graph[u].begin(); it != Graph[u].end();
  192.             it++) {
  193.         int v = *it;
  194.         if (v == dad[u])
  195.             continue;
  196.         if (subSize[v] > most)
  197.             most = subSize[v], ind = v;
  198.     }
  199.  
  200.     if (ind >= 0)
  201.         HLD(ind);
  202.  
  203.     for (vector<int>::iterator it = Graph[u].begin(); it != Graph[u].end();
  204.             it++) {
  205.         int v = *it;
  206.         if (v == dad[u] || v == ind)
  207.             continue;
  208.         ++chainNo;
  209.         HLD(v);
  210.     }
  211. }
  212.  
  213. vector<segtree> decomp;
  214.  
  215. int hld_find(int u, int l) {
  216.     int soFar = 0;
  217.     while (true) {
  218.         int c = chainIndex[u];
  219.  
  220.         if (c != chainIndex[l]) {
  221.             soFar = gcd(soFar, decomp[c].query(0, chainPos[u]));
  222.             u = dad[u];
  223.         } else {
  224.             soFar = gcd(soFar, decomp[c].query(chainPos[l], chainPos[u]));
  225.             break;
  226.         }
  227.     }
  228.     return soFar;
  229. }
  230.  
  231. void hld_change(int u, int l, int d) {
  232.     while (true) {
  233.         int c = chainIndex[u];
  234.  
  235.         if (c != chainIndex[l]) {
  236.             decomp[c].update(0, chainPos[u], d);
  237.             u = dad[u];
  238.         } else {
  239.             decomp[c].update(chainPos[l], chainPos[u], d);
  240.             break;
  241.         }
  242.     }
  243. }
  244.  
  245. void solve() {
  246.     memset(dad, -2, sizeof(dad));
  247.     dfs(0, N, 0);
  248.     dad[0] = -1;
  249.     LCA lca(vector<int>(dad, dad + N), vector<int>(level, level + N));
  250.     chainNo = 0;
  251.     HLD(0);
  252.     chainNo++;
  253.     for (int c = 0; c < chainNo; c++) {
  254.         vector<int> its;
  255.         for (vector<int>::iterator it = chain[c].begin(); it != chain[c].end();
  256.                 it++) {
  257.             its.push_back(A[*it]);
  258.         }
  259.         decomp.push_back(segtree(its));
  260.     }
  261.  
  262.     int Q;
  263.     scanf("%d", &Q);
  264.     char cmd[5];
  265.     int u, v, d;
  266.     for (int i = 0; i < Q; i++) {
  267.         scanf("%s", cmd);
  268.         scanf("%d", &u);
  269.         scanf("%d", &v);
  270.         int l = lca.query(u, v);
  271.         if (cmd[0] == 'F') {
  272.             int ans = gcd(hld_find(u, l), hld_find(v, l));
  273.             printf("%d\n", ans);
  274.         }
  275.  
  276.         else {
  277.             scanf("%d", &d);
  278.             hld_change(u, l, d);
  279.             hld_change(v, l, d);
  280.             hld_change(l, l, -d); // we've added a term of d to lca twice, better remove once.
  281.         }
  282.     }
  283. }
  284.  
  285. bool input() {
  286.     scanf("%d", &N);
  287.     for (int i = 0; i < N - 1; i++) {
  288.         int a, b;
  289.         scanf("%d", &a);
  290.         scanf("%d", &b);
  291.         Graph[a].push_back(b);
  292.         Graph[b].push_back(a);
  293.     }
  294.  
  295.     for (int i = 0; i < N; i++)
  296.         scanf("%d", &A[i]);
  297.     return true;
  298. }
  299.  
  300. int main() {
  301.     int T = 1;
  302.     for (testnum = 1; testnum <= T; testnum++) {
  303.         if (!input())
  304.             break;
  305.         solve();
  306.     }
  307. }
Advertisement
Add Comment
Please, Sign In to add comment