洛谷P1494 [國家集訓隊]小Z的襪子 題解 普通莫隊算法

題目鏈接:https://www.luogu.com.cn/problem/P1494

解題思路:

普通莫隊算法。

使用 \(c[i]\) 表示第 \(i\) 只襪子的顏色、\(cnt[i]\) 表示當前區間顏色 \(i\) 的襪子數量,
同時維護 \(res\) 記錄當前的區間中存在多少對相同顏色的襪子。

對於當前區間 \([l,r]\) ,總對數爲 \(tot = \frac{(r-l+1) \times (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\n", ans[i].first, ans[i].second);
    return 0;
}

參考資料:http://oi-wiki.com/misc/mo-algo/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章