莫队算法
2016-07-24 23:08
711 查看
ACM模版
参考题目链接:
BZOJ 2038 [2009国家集训队]小Z的袜子(hose)
题解:
只需要统计区间内各个数出现次数的平方和。
莫队算法,两种方法,一种是直接分成sqrt(n)块,分块排序。
另外一种是求得曼哈顿距离最小生成树,根据manhattan MST的dfs序求解。
莫队算法
可以解决一类静态,离线区间查询问题。参考题目链接:
BZOJ 2038 [2009国家集训队]小Z的袜子(hose)
题解:
只需要统计区间内各个数出现次数的平方和。
莫队算法,两种方法,一种是直接分成sqrt(n)块,分块排序。
另外一种是求得曼哈顿距离最小生成树,根据manhattan MST的dfs序求解。
分块
const int MAXN = 50010; const int MAXM = 50010; struct Query { int L, R, id; } node[MAXM]; long long gcd(long long a, long long b) { if (b == 0) { return a; } return gcd(b, a % b); } struct Ans { long long a, b; // 分数a/b void reduce() // 分数化简 { long long d = gcd(a, b); a /= d; b /= d; return ; } } ans[MAXM]; int a[MAXN]; int num[MAXN]; int n, m, unit; bool cmp(Query a, Query b) { if (a.L / unit != b.L / unit) { return a.L / unit < b.L / unit; } else { return a.R < b.R; } } void work() { long long temp = 0; memset(num, 0, sizeof(num)); int L = 1; int R = 0; for (int i = 0; i < m; i++) { while (R < node[i].R) { R++; temp -= (long long)num[a[R]] * num[a[R]]; num[a[R]]++; temp += (long long)num[a[R]] * num[a[R]]; } while (R > node[i].R) { temp -= (long long)num[a[R]] * num[a[R]]; num[a[R]]--; temp += (long long)num[a[R]] * num[a[R]]; R--; } while (L < node[i].L) { temp -= (long long)num[a[L]] * num[a[L]]; num[a[L]]--; temp += (long long)num[a[L]] * num[a[L]]; L++; } while (L > node[i].L) { L--; temp -= (long long)num[a[L]] * num[a[L]]; num[a[L]]++; temp += (long long)num[a[L]] * num[a[L]]; } ans[node[i].id].a = temp - (R - L + 1); ans[node[i].id].b = (long long)(R - L + 1) * (R - L); ans[node[i].id].reduce(); } return ; } int main() { while (scanf("%d%d", &n, &m) == 2) { for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } for (int i = 0; i < m; i++) { node[i].id = i; scanf("%d%d", &node[i].L, &node[i].R); } unit = (int)sqrt(n); sort(node,node+m,cmp); work(); for (int i = 0; i < m; i++) { printf("%lld/%lld\n", ans[i].a, ans[i].b); } } return 0; }
Manhattan MST的dfs顺序求解
const int MAXN = 50010; const int MAXM = 50010; const int INF = 0x3f3f3f3f; struct Point { int x, y, id; } p[MAXN], pp[MAXN]; bool cmp(Point a, Point b) { if (a.x != b.x) { return a.x < b.x; } else { return a.y < b.y; } } // 树状数组,找y-x大于当前的,但是y+x最小的 struct BIT { int min_val,pos; void init() { min_val = INF; pos = -1; return ; } } bit[MAXN]; struct Edge { int u, v, d; } edge[MAXN << 2]; bool cmpedge(Edge a, Edge b) { return a.d < b.d; } int tot; int n; int F[MAXN]; int find(int x) { if (F[x] == -1) { return x; } else { return F[x] = find(F[x]); } } void addedge(int u, int v, int d) { edge[tot].u = u; edge[tot].v = v; edge[tot++].d = d; return ; } struct Graph { int to,next; } e[MAXN << 1]; int total, head[MAXN]; void _addedge(int u, int v) { e[total].to = v; e[total].next = head[u]; head[u] = total++; return ; } int lowbit(int x) { return x & (-x); } void update(int i, int val, int pos) { while (i > 0) { if (val < bit[i].min_val) { bit[i].min_val = val; bit[i].pos = pos; } i -= lowbit(i); } return ; } int ask(int i, int m) { int min_val = INF, pos = -1; while (i <= m) { if (bit[i].min_val < min_val) { min_val = bit[i].min_val; pos = bit[i].pos; } i += lowbit(i); } return pos; } int dist(Point a, Point b) { return abs(a.x - b.x) + abs(a.y - b.y); } void Manhattan_minimum_spanning_tree(int n, Point p[]) { int a[MAXN], b[MAXN]; tot = 0; for (int dir = 0; dir < 4; dir++) { if (dir == 1 || dir == 3) { for (int i = 0; i < n; i++) { swap(p[i].x, p[i].y); } } else if (dir == 2) { for (int i = 0; i < n; i++) { p[i].x = -p[i].x; } } sort(p, p + n, cmp); for (int i = 0; i < n; i++) { a[i] = b[i] = p[i].y - p[i].x; } sort(b, b + n); int m = (int)(unique(b, b + n) - b); for (int i = 1; i <= m; i++) { bit[i].init(); } for (int i = n - 1; i >= 0; i--) { int pos = (int)(lower_bound(b, b + m, a[i]) - b + 1); int ans = ask(pos, m); if (ans != -1) { addedge(p[i].id, p[ans].id, dist(p[i],p[ans])); } update(pos, p[i].x + p[i].y, i); } } memset(F, -1, sizeof(F)); sort(edge, edge + tot, cmpedge); total = 0; memset(head, -1, sizeof(head)); for (int i = 0; i < tot; i++) { int u = edge[i].u, v = edge[i].v; int t1 = find(u), t2 = find(v); if (t1 != t2) { F[t1] = t2; _addedge(u, v); _addedge(v, u); } } return ; } int m; int a[MAXN]; struct Ans { long long a, b; } ans[MAXM]; long long temp ; int num[MAXN]; void add(int l, int r) { for (int i = l; i <= r; i++) { temp -= (long long)num[a[i]] * num[a[i]]; num[a[i]]++; temp += (long long)num[a[i]] * num[a[i]]; } return ; } void del(int l, int r) { for (int i = l; i <= r; i++) { temp -= (long long)num[a[i]] * num[a[i]]; num[a[i]]--; temp += (long long)num[a[i]] * num[a[i]]; } return ; } void dfs(int l1, int r1, int l2, int r2, int idx, int pre) { if (l2 < l1) { add(l2, l1 - 1); } if (r2 > r1) { add(r1 + 1, r2); } if (l2 > l1) { del(l1, l2 - 1); } if (r2 < r1) { del(r2 + 1, r1); } ans[pp[idx].id].a = temp - (r2 - l2 + 1); ans[pp[idx].id].b = (long long)(r2 - l2 + 1) * (r2 - l2); for (int i = head[idx]; i != -1; i = e[i].next) { int v = e[i].to; if (v == pre) { continue; } dfs(l2, r2, pp[v].x, pp[v].y, v, idx); } if (l2 < l1) { del(l2, l1 - 1); } if (r2 > r1) { del(r1 + 1, r2); } if (l2 > l1) { add(l1, l2 - 1); } if (r2 < r1) { add(r2 + 1, r1); } return ; } long long gcd(long long a, long long b) { if (b == 0) { return a; } else { return gcd(b, a % b); } } int main() { while (scanf("%d%d", &n, &m) == 2) { for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } for (int i = 0; i < m; i++) { scanf("%d%d", &p[i].x, &p[i].y); p[i].id = i; pp[i] = p[i]; } Manhattan_minimum_spanning_tree(m, p); memset(num, 0, sizeof(num)); temp = 0; dfs(1, 0, pp[0].x, pp[0].y, 0, -1); for (int i = 0; i < m; i++) { long long d = gcd(ans[i].a, ans[i].b); printf("%lld/%lld\n", ans[i].a / d, ans[i].b / d); } } return 0; }
相关文章推荐
- 2013BJOI Day1 第二题 彩色球
- 小z的袜子题后小结
- 【学习】莫队算法
- hdu 5381 莫队算法/gcd
- bzoj-3585 mex
- 1188 - Fast Queries (莫队算法)
- 树状数组写区间最大值
- Codeforces 617E ( 莫队算法 Mo's algorithm )
- 小Z的袜子(莫队算法)
- hdu 5213(容斥原理+莫队算法)
- hdu 4358(莫队算法+dfs序列)
- 小Z的袜子【莫队算法】
- WOJ 1605 Distance on Tree(莫队算法)
- WOJ 1578 Fishing Dream(莫队算法)
- hdu 5145 NPY and girls (莫队算法)
- Codeforces Round #340 (Div. 2) E XOR and Favorite Number
- BZOJ 2038 小Z的袜子(hose)(莫队算法)
- Codeforces Round #340 (Div. 2) E. XOR and Favorite Number(莫队算法)
- NBUT 1457 Sona(莫队算法)
- HDU 4358 Boring counting 莫队算法