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 ", p[i].fz, p[i].fm); 50 } 51 return 0; 52 }