# BZOJ 2038 小Z的袜子(hose) 莫队算法模板题

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

 1 #include<bits/stdc++.h>
2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数，会超时
4 #define Min(a, b) ((a) < (b) ? (a) : (b))
5 #define Mem(a) memset(a, 0, sizeof(a))
6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
7 #define MID(l, r) ((l) + ((r) - (l)) / 2)
8 #define lson ((o)<<1)
9 #define rson ((o)<<1|1)
11 using namespace std;
13 {
14     int x=0,f=1;char ch=getchar();
15     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
16     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
17     return x*f;
18 }
19
20 typedef long long ll;
21 const int maxn = 1000000 + 10;
22 const int MOD = 1000000007;//const引用更快，宏定义也更快
23 const ll INF = 1e16;
24 const double eps = 1e-6;
25
26 int a[maxn];
27 int pos[maxn];//存储每一位分块编号
28 struct query
29 {
30     int l, r, id;
31     query(){}
32     query(int l, int r, int id):l(l), r(r), id(id){}
33     bool operator <(const query& a)const
34     {
35         if(pos[l] == pos[a.l])return r < a.r;//在同一分块内 莫队算法核心
36         return l < a.l;
37     }
38 }b[maxn];
39 ll num[maxn];//num[i]表示当前数字i出现的次数
40 ll ans;//ans的含义如下：维护当前区间内数字出现次数平方和
41 //分子 = For i = 1...n  num[i]*(num[i] - 1) / 2
42 //分母 = (R - L + 1) * (R - L) / 2
43 //转化一下得：
44 //分子 = (For i = 1...n num[i]^2) - (For i = 1..n num[i]) = ans - (R - L + 1)
45 //分母 = (R - L + 1) * (R - L)
47 {
48     ans -= num[a[p]] * num[a[p]];//先把下标p的数字贡献删去
50     ans += num[a[p]] * num[a[p]];//加上下标p数字贡献
51 }
52 struct node
53 {
54     ll a, b;
55     node(){}
56     node(ll a, ll b):a(a), b(b){}
57 }Ans[maxn];
58 int main()
59 {
60     int n, m;
61     scanf("%d%d", &n, &m);
62     for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
63     int len = (int)sqrt(n);
64     for(int i = 1; i <= n; i++)pos[i] = i / len + 1;
65     for(int i = 1; i <= m; i++)scanf("%d %d", &b[i].l, &b[i].r), b[i].id = i;
66     sort(b + 1, b + 1 + m);
67     int l = 1, r = 0;
68     ll tmpa, tmpb;
69     for(int i = 1; i <= m; i++)
70     {
71         for(; r < b[i].r; r++)update(r + 1, 1);
72         for(; r > b[i].r; r--)update(r, -1);
73         for(; l < b[i].l; l++)update(l, -1);
74         for(; l > b[i].l; l--)update(l - 1, 1);//莫队写法
75         tmpa = ans - (b[i].r - b[i].l + 1);
76         tmpb = (ll)(b[i].r - b[i].l + 1) * (b[i].r - b[i].l);
77         ll g = __gcd(tmpa, tmpb);
78         tmpa /= g, tmpb /= g;
79         Ans[b[i].id] = node(tmpa, tmpb);
80     }
81     for(int i = 1; i <= m; i++)printf("%lld/%lld\n", Ans[i].a, Ans[i].b);
82     return 0;
83 }
84 

posted @ 2018-09-18 21:12  _努力努力再努力x  阅读(215)  评论(0编辑  收藏  举报