Loading

BZOJ 2038: [2009国家集训队]小Z的袜子(hose)(莫队算法)

http://www.lydsy.com/JudgeOnline/problem.php?id=2038

题意:……

思路:莫队算法学习可以看这个:http://www.cnblogs.com/hzf-sbit/p/4056874.html

大概就是一种离线算法,通过排序优化询问序列,然后可以在O(n^1.5)的复杂度内暴力处理一些不带修改的区间询问问题吧。

首先我们可以列出式子:ans = C(∑col[i],2) / C(r - l + 1, 2) = ∑(col[i] * col[i] - col[i]) / ((r - l) * (r - l + 1))。

当我们从[L, R]区间变成[L, R+1]的时候,更新只需要执行:ans -= col[a[R+1]] * col[a[R+1]] - col[a[R+1]]; col[a[R+1]] += w; ans +=  col[a[R+1]] * col[a[R+1]] - col[a[R+1]];从左边变化也是如此。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 #define N 50010
 7 typedef long long LL;
 8 struct node {
 9     int l, r, id;
10     LL fz, fm;
11 } p[N];
12 int n, m, kuai;
13 LL a[N], col[N], ans;
14 
15 bool cmpid(const node &a, const node &b) { return a.id < b.id; }
16 bool cmp(const node &a, const node &b) {
17     if(a.l / kuai == b.l / kuai) return a.r < b.r;
18     return a.l / kuai < b.l / kuai;
19 }
20 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; }
21 void update(int id, int w) {
22     ans -= col[a[id]] * col[a[id]] - col[a[id]];
23     col[a[id]] += w;
24     ans += col[a[id]] * col[a[id]] - col[a[id]];
25 }
26 
27 int main() {
28    while(~scanf("%d%d", &n, &m)) {
29         memset(col, 0, sizeof(col));
30         for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
31         for(int i = 1; i <= m; i++) scanf("%d%d", &p[i].l, &p[i].r), p[i].id = i;
32         int L = 1, R = 0; kuai = sqrt(n);
33         sort(p + 1, p + 1 + m, cmp);
34         LL fz = 0, fm = 0; ans = 0;
35         for(int i = 1; i <= m; i++) {
36             LL l = p[i].l, r = p[i].r;
37             for( ; R < r; R++) update(R + 1, 1);
38             for( ; R > r; R--) update(R, -1);
39             for( ; L > l; L--) update(L - 1, 1);
40             for( ; L < l; L++) update(L, -1);
41             if(l == r) { p[i].fz = 0; p[i].fm = 1; continue; }
42             fz = ans;
43             fm = (r - l + 1) * (r - l);
44             LL yue = gcd(fz, fm);
45             fz /= yue; fm /= yue;
46             p[i].fz = fz; p[i].fm = fm;
47         }
48         sort(p + 1, p + 1 + m, cmpid);
49         for(int i = 1; i <= m; i++) printf("%lld/%lld\n", p[i].fz, p[i].fm);
50     }
51     return 0;
52 }

 

posted @ 2017-01-24 22:19  Shadowdsp  阅读(273)  评论(4编辑  收藏  举报