1 /*
2 莫队算法:求出[l, r]上取出两只相同袜子的个数。
3 莫队算法是离线处理一类区间不修改查询类问题的算法。如果你知道了[L,R]的答案,可以在O(1)的时间下得到
4 [L,R-1]和[L,R+1]和[L-1,R]和[L+1,R],4个while是精华!
5 对于莫队算法我感觉就是暴力。只是预先知道了所有的询问。可以合理的组织计算每个询问的顺序以此来降低复杂度。
6 详细解释:http://blog.csdn.net/bossup/article/details/39236275
7 */
8 #include <cstdio>
9 #include <cstring>
10 #include <algorithm>
11 #include <cmath>
12 using namespace std;
13
14 typedef long long ll;
15 const int MAXN = 5e4 + 10;
16 const int INF = 0x3f3f3f3f;
17 struct Data
18 {
19 int b, l, r, id;
20 ll x, y;
21 Data () {}
22 Data (int b, ll l, ll r, int id) : b (b), l (l), r (r), id (id) {};
23 }data[MAXN];
24 int cnt[MAXN];
25 int a[MAXN];
26 int n, m;
27 ll ans;
28
29 bool cmp_pre(Data x, Data y)
30 {
31 if (x.b == y.b) return x.r < y.r;
32 return x.b < y.b;
33 }
34
35 bool cmp_id(Data x, Data y) {return x.id < y.id;}
36
37 ll cal(int v) {return (ll) v * v;}
38
39 void updata(int v, int add)
40 {
41 ans -= cal (cnt[v]);
42 cnt[v] += add;
43 ans += cal (cnt[v]);
44 }
45
46 ll GCD(ll a, ll b) {return b == 0 ? a : GCD (b, a % b);}
47
48 void Modui(void)
49 {
50 sort (data+1, data+1+m, cmp_pre);
51 memset (cnt, 0, sizeof (cnt));
52
53 int l = 1, r = 0; ans = 0;
54 for (int i=1; i<=m; ++i)
55 {
56 while (data[i].l < l) updata (a[--l], 1);
57 while (data[i].l > l) updata (a[l], -1), l++;
58 while (data[i].r > r) updata (a[++r], 1);
59 while (data[i].r < r) updata (a[r], -1), r--;
60
61 if (data[i].l == data[i].r)
62 {
63 data[i].x = 0; data[i].y = 1;
64 continue;
65 }
66 data[i].x = ans - (data[i].r - data[i].l + 1);
67 data[i].y = (ll) (data[i].r - data[i].l + 1) * (data[i].r - data[i].l);
68 ll k = GCD (data[i].x, data[i].y);
69 data[i].x /= k; data[i].y /= k;
70 }
71
72 sort (data+1, data+1+m, cmp_id);
73 for (int i=1; i<=m; ++i)
74 {
75 printf ("%lld/%lld
", data[i].x, data[i].y);
76 }
77 }
78
79 int main(void) //BOJ 2038 [2009国家集训队]小Z的袜子(hose)
80 {
81 // freopen ("BZOJ_2038.in", "r", stdin);
82
83 while (scanf ("%d%d", &n, &m) == 2)
84 {
85 for (int i=1; i<=n; ++i) scanf ("%d", &a[i]);
86
87 int block = (int) sqrt (n * 1.0);
88 for (int i=1; i<=m; ++i)
89 {
90 int l, r;
91 scanf ("%d%d", &l, &r);
92 data[i] = Data (l / block, l, r, i);
93 }
94
95 Modui ();
96 }
97
98 return 0;
99 }