首页 > 代码库 > (树上莫队)HDU - 5799 This world need more Zhu

(树上莫队)HDU - 5799 This world need more Zhu

题意:

两种询问:

1、询问以u为根的子树中出现的a次的数的和与出现b次的数的和的gcd。

2、询问u到v的树链中出现的a次的数的和与出现b次的数的和的gcd。

有点绕。。

 

分析:

因为自己不会树上莫队,所以学习了一波。

但是对于子树我还是有所经验,可以转成dfs序来做,之前有做过类似的题,比如这题。

然而对于树链有点懵逼,虽然我觉得也能用dfs序做,不过看大佬们的dfs序做的树链查询,也有点懵,感觉写起来很麻烦。

貌似是修改了dfs序,回溯的时候不再只是和进入时相同的序,而是独立的序。

还是感觉麻烦。。后来发现一个基于树分块的树上莫队,感觉很强。代码显然没有前者复杂。所以就用了它。

第一种询问其实有nlogn的做法,跟上面的之前做过的 dfs序题是同一题。

但是这里写的代码好长啊。。虽然很挫。。

 

代码:

  1 #include <iostream>  2 #include <cstdio>  3 #include <algorithm>  4 #include <cmath>  5 #include <cstring>  6 #include <set>  7 #include <vector>  8 #include <queue>  9 #include <map> 10 #include <list> 11 #include <bitset> 12 #include <string> 13 #include <cctype> 14 #include <cstdlib> 15  16 using namespace std; 17  18 typedef long long ll; 19 typedef unsigned long long ull; 20 #define inf (0x3f3f3f3f) 21 #define lnf (0x3f3f3f3f3f3f3f3f) 22 #define eps (1e-8) 23 int sgn(double a) { 24     return a < -eps ? -1 : a < eps ? 0 : 1; 25 } 26  27 const int maxn = 100010; 28  29 int t; 30 struct Q { 31     int u, v, a, b; 32     int l, r; 33     int index; 34 }; 35  36  37 int col[maxn]; 38 int cnt[maxn]; 39 ll cs[maxn]; 40 ll ans[maxn]; 41 const int bk = 316; 42  43 const int DEG = 20; 44 vector<Q> query[3]; 45 vector<int> g[maxn]; 46  47 int n, q; 48 int a[maxn], b[maxn]; 49  50 inline bool scan_d(int &num) { 51     char in; 52     bool IsN = false; 53     in = getchar(); 54     if(in == EOF) return false; 55     while(in != - && (in < 0 || in > 9)) in = getchar(); 56     if(in == -) { 57         IsN = true; 58         num = 0; 59     } else num = in - 0; 60     while(in = getchar(), in >= 0 && in <= 9) { 61         num *= 10, num += in - 0; 62     } 63     if(IsN) num = -num; 64     return true; 65 } 66  67 void initHash() { 68     for(int i = 1; i <= n; i++) { 69         b[i] = a[i]; 70     } 71     sort(b + 1, b + n + 1); 72     int p = unique(b + 1, b + n + 1) - b - 1; 73     for(int i = 1; i <= n; i++) { 74         a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b; 75     } 76 } 77  78 int L[maxn]; 79 int R[maxn]; 80 int d[maxn]; 81 int tot = 0; 82  83 void dfs(int u, int fa, int dep) { 84     L[u] = ++tot; 85     d[u] = dep; 86     col[tot] = a[u]; 87     for (int i = 0; i < g[u].size(); i++) { 88         int v = g[u][i]; 89         if (v == fa)continue; 90         dfs(v, u, dep + 1); 91     } 92     R[u] = tot; 93 } 94  95  96  97 bool cmp(Q a, Q b) { 98     if(a.l / bk == b.l / bk)return a.r < b.r; 99     else return a.l / bk < b.l / bk;100 }101 102 103 /// find_block104 int block[maxn], bcnt, bsize;105 int stk[maxn], top;106 107 void add_block(int &cnt) {108     while(cnt--) block[stk[--top]] = bcnt;109     bcnt++;110     cnt = 0;111 }112 113 void rest_block() {114     while(top) block[stk[--top]] = bcnt - 1;115 }116 117 int dfs_block(int u, int f) {118     int s = 0;119     for(int i = 0; i < g[u].size(); i++) {120         int v = g[u][i];121         if(v == f) continue;122         s += dfs_block(v, u);123         if(s >= bsize) add_block(s);124     }125     stk[top++] = u;126     s++;127     if(s >= bsize) add_block(s);128     return s;129 }130 131 void init_block() {132     bsize = bk;133     dfs_block(1, 0);134     rest_block();135 }136 137 138 /// ask_rmq139 int fa[DEG][maxn];140 int dep[maxn];141 142 void dfs_lca(int u, int f, int depth) {143     dep[u] = depth;144     fa[0][u] = f;145     for(int i = 0; i < g[u].size(); i++) {146         int v = g[u][i];147         if(v != f) dfs_lca(v, u, depth + 1);148     }149 }150 151 void init_lca() {152     dfs_lca(1, -1, 0);153     for(int k = 0; k + 1 < DEG; ++k) {154         for(int u = 1; u <= n; ++u) {155             if(fa[k][u] == -1) fa[k + 1][u] = -1;156             else fa[k + 1][u] = fa[k][fa[k][u]];157         }158     }159 }160 161 int ask_lca(int u, int v) {162     if(dep[u] < dep[v]) swap(u, v);163     for(int k = 0; k < DEG; ++k) {164         if((dep[u] - dep[v]) & (1 << k)) u = fa[k][u];165     }166     if(u == v) return u;167     for(int k = DEG - 1; k >= 0; --k) {168         if(fa[k][u] != fa[k][v])169             u = fa[k][u], v = fa[k][v];170     }171     return fa[0][u];172 }173 /// modui174 bool vis[maxn];175 176 void xorNode(int u) {177     if(vis[u]) {178         vis[u] = false;179         cs[cnt[a[u]]] -= b[a[u]];180         cnt[a[u]]--;181         cs[cnt[a[u]]] += b[a[u]];182     } else {183         vis[u] = true;184         cs[cnt[a[u]]] -= b[a[u]];185         cnt[a[u]]++;186         cs[cnt[a[u]]] += b[a[u]];187     }188 }189 190 void xorPathWithoutLca(int u, int v) {191     if(dep[u] < dep[v]) swap(u, v);192     while(dep[u] != dep[v])193         xorNode(u), u = fa[0][u];194     while(u != v)195         xorNode(u), u = fa[0][u], xorNode(v), v = fa[0][v];196 }197 198 void moveNode(int u, int v, int taru, int tarv) {199     xorPathWithoutLca(u, taru);200     xorPathWithoutLca(v, tarv);201     //printf("debug %d %d\n", ask_lca(u, v), ask_lca(taru, tarv));202     xorNode(ask_lca(u, v));203     xorNode(ask_lca(taru, tarv));204 }205 206 207 bool cmp2(Q a, Q b) {208     if(block[a.u] == block[b.u])return block[a.v] < block[b.v];209     else return block[a.u] < block[b.u];210 }211 212 213 void solve() {214     scan_d(t);215     int c = 0;216     while(t--) {217         tot = 0;218         memset(cs, 0, sizeof(cs));219         memset(cnt, 0, sizeof(cnt));220         memset(vis, 0, sizeof(vis));221         for(int i = 1; i <= n; i++) {222             g[i].clear();223         }224         query[1].clear();225         query[2].clear();226         scan_d(n);227         scan_d(q);228         for(int i = 1; i <= n; i++) {229             scan_d(a[i]);230         }231         initHash();232         for(int i = 0; i < n - 1; i++) {233             int u, v;234             scan_d(u);235             scan_d(v);236             g[u].push_back(v);237             g[v].push_back(u);238         }239         dfs(1, -1, 1);240         init_block();241         init_lca();242         for(int i = 0; i < q; i++) {243             int op, u, v, a, b;244             scan_d(op);245             scan_d(u);246             scan_d(v);247             scan_d(a);248             scan_d(b);249             query[op].push_back(Q{u, v, a, b, L[u], R[u], i});250         }251         sort(query[1].begin(), query[1].end(), cmp);252 253 254         int pl = 1, pr = 0;255 256         for (int i = 0; i < query[1].size(); i++) {257             int index = query[1][i].index;258             if (pr < query[1][i].r) {259                 for (int j = pr + 1; j <= query[1][i].r; j++) {260                     cs[cnt[col[j]]] -= b[col[j]];261                     cnt[col[j]]++;262                     cs[cnt[col[j]]] += b[col[j]];263                 }264             } else {265                 for (int j = pr; j > query[1][i].r; j--) {266                     cs[cnt[col[j]]] -= b[col[j]];267                     cnt[col[j]]--;268                     cs[cnt[col[j]]] += b[col[j]];269                 }270             }271             pr = query[1][i].r;272             if (pl < query[1][i].l) {273                 for (int j = pl; j < query[1][i].l; j++) {274                     cs[cnt[col[j]]] -= b[col[j]];275                     cnt[col[j]]--;276                     cs[cnt[col[j]]] += b[col[j]];277                 }278             } else {279                 for (int j = pl - 1; j >= query[1][i].l; j--) {280                     cs[cnt[col[j]]] -= b[col[j]];281                     cnt[col[j]]++;282                     cs[cnt[col[j]]] += b[col[j]];283                 }284             }285             pl = query[1][i].l;286             ans[index] = __gcd(cs[query[1][i].a], cs[query[1][i].b]);287         }288         memset(cs, 0, sizeof(cs));289         memset(cnt, 0, sizeof(cnt));290 291 292         for(int i = 0; i < query[2].size(); i++) {293             if(block[query[2][i].u] > block[query[2][i].v]) swap(query[2][i].u, query[2][i].v);294         }295         sort(query[2].begin(), query[2].end(), cmp2);296 297         int nowu = 1, nowv = 1;298         xorNode(1);299         for(int i = 0; i < query[2].size(); i++) {300             int index = query[2][i].index;301             moveNode(nowu, nowv, query[2][i].u, query[2][i].v);302             ans[index] = __gcd(cs[query[2][i].a], cs[query[2][i].b]);303             nowu = query[2][i].u, nowv = query[2][i].v;304         }305         printf("Case #%d:\n", ++c);306         for(int i = 0; i < q; i++) {307             printf("%lld\n", ans[i]);308         }309 310     }311 312 }313 314 315 316 int main() {317 318 #ifndef ONLINE_JUDGE319     freopen("1.in", "r", stdin);320     //freopen("1.out", "w", stdout);321 #endif322     //iostream::sync_with_stdio(false);323     solve();324     return 0;325 }

 

(树上莫队)HDU - 5799 This world need more Zhu