洛谷 P1494 [國家集訓隊]小Z的襪子
阿新 • • 發佈:2018-08-12
國家集訓隊 using 一個 gcd sort -- [1] include type
題意簡述
一些襪子排成一排,每個襪子有固定的顏色。
每次詢問在[l,r]的襪子中等概率選兩只,求有多大的概率抽到兩只一樣顏色的。
題解思路
維護一個計數數組cnt[i]表示當前[l,r]區間顏色為i的襪子有幾只。
轉移的時候如果加入元素x,那麽cnt[x]變成cnt[x]+1,對答案的貢獻為2cnt[x]+1
代碼
#include <cmath> #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; struct Q{ int l, r, i; ll len; }b[50010]; int n, m, len, lal, lar; int a[50010], bnum[50010], cnt[50010]; ll s; ll ans[50010][2]; bool cmp(Q x, Q y) { return bnum[x.l] == bnum[y.l] ? bnum[x.r] < bnum[y.r] : bnum[x.l] < bnum[y.l]; } void add(int x) { s += (cnt[x] << 1) | 1; ++cnt[x]; } void del(int x) { s -= (cnt[x] << 1) - 1; --cnt[x]; } int main() { scanf("%d%d", &n, &m); len = sqrt(n); for (register int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (register int i = 1; i <= n; ++i) bnum[i] = (i - 1) / len + 1; for (register int i = 1; i <= m; ++i) { scanf("%d%d", &b[i].l, &b[i].r); b[i].i = i; b[i].len = b[i].r - b[i].l + 1; } sort(b + 1, b + m + 1, cmp); for (register int i = b[1].l; i <= b[1].r; ++i) add(a[i]); if (s != b[1].len) { ll x1 = s - b[1].len, x2 = b[1].len * (b[1].len - 1); ll g = __gcd(x1, x2); ans[b[1].i][0] = x1 / g; ans[b[1].i][1] = x2 / g; } else ans[b[1].i][1] = 1; lal = b[1].l; lar = b[1].r; for (register int i = 2; i <= m; ++i) { while (lal > b[i].l) add(a[--lal]); while (lar < b[i].r) add(a[++lar]); while (lal < b[i].l) del(a[lal++]); while (lar > b[i].r) del(a[lar--]); if (s != b[i].len) { ll x1 = s - b[i].len, x2 = b[i].len * (b[i].len - 1); ll g = __gcd(x1, x2); ans[b[i].i][0] = x1 / g; ans[b[i].i][1] = x2 / g; } else ans[b[i].i][1] = 1; } for (register int i = 1; i <= m; ++i) printf("%lld/%lld\n", ans[i][0], ans[i][1]); }
洛谷 P1494 [國家集訓隊]小Z的襪子