zoukankan      html  css  js  c++  java
  • 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
    ", p[i].fz, p[i].fm);
    50     }
    51     return 0;
    52 }
  • 相关阅读:
    Java Math 取整的方式
    Java final 关键词修饰类、方法、变量
    Android Activity 开发常用技巧整理
    Java override 和 overload 的区别
    Android TextView 常用技巧
    Android Adb 常用命令
    Android 实现应用升级方案(暨第三方自动升级服务无法使用后的解决方案)
    Git 常用命令
    Android 常见Crash Log汇总
    Java Annotation 总结
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6347925.html
Copyright © 2011-2022 走看看