题目链接:https://www.luogu.com.cn/problem/P1494
解题思路:
普通莫队算法。
使用 (c[i]) 表示第 (i) 只袜子的颜色、(cnt[i]) 表示当前区间颜色 (i) 的袜子数量,
同时维护 (res) 记录当前的区间中存在多少对相同颜色的袜子。
对于当前区间 ([l,r]) ,总对数为 (tot = frac{(r-l+1) imes (r-l)}{2}),所以比值为 (frac{res}{tot})(注意可能需要约分)。
示例代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50050;
int n, m, sn, c[maxn], cnt[maxn];
long long res;
pair<long long, long long> ans[maxn];
struct Query {
int l, r, id;
bool operator < (const Query &b) const {
return l / sn < b.l / sn || l / sn == b.l / sn && r < b.r;
}
} q[maxn];
void add(int i) {
res += cnt[c[i]];
cnt[c[i]] ++;
}
void del(int i) {
cnt[c[i]] --;
res -= cnt[c[i]];
}
int main() {
scanf("%d%d", &n, &m);
sn = sqrt(n);
for (int i = 1; i <= n; i ++) scanf("%d", c+i);
for (int i = 0; i < m; i ++) {
scanf("%d%d", &q[i].l, &q[i].r);
q[i].id = i;
}
sort(q, q+m);
for (int i = 0, l = 1, r = 0; i < m; i ++) {
if (q[i].l == q[i].r) {
ans[q[i].id] = { 0, 1 };
continue;
}
while (l > q[i].l) add(--l);
while (r < q[i].r) add(++r);
while (l < q[i].l) del(l++);
while (r > q[i].r) del(r--);
if (res == 0) ans[q[i].id] = { 0, 1 };
else {
long long tot = (long long)(r - l + 1) * (r - l) / 2;
long long tmp = __gcd(res, tot);
ans[q[i].id] = { res/tmp, tot/tmp };
}
}
for (int i = 0; i < m; i ++) printf("%lld/%lld
", ans[i].first, ans[i].second);
return 0;
}