1. 程式人生 > >洛谷P1494 小Z的襪子

洛谷P1494 小Z的襪子

題意:在[l, r]之中任選兩個數,求它們相同的概率。

解:

莫隊入門。

概率這個很好搞,就是cnt * (cnt - 1) / 2。

然後發現每次挪指標的時候,某一個cnt會+1或-1。這時候差值就是2 * cntsmall

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cmath>
 4 
 5 typedef long long LL;
 6 const int N = 50010;
 7 
 8 int a[N], bin[N], fr[N];
 9 LL ans;
10 11 struct ASK { 12 int id, l, r; 13 LL ans; 14 inline bool operator <(const ASK &w) const { 15 if(fr[l] != fr[w.l]) { 16 return fr[l] < fr[w.l]; 17 } 18 return r < w.r; 19 } 20 }ask[N]; 21 22 inline bool cmp(const ASK &a, const ASK &b) {
23 return a.id < b.id; 24 } 25 26 inline LL gcd(LL a, LL b) { 27 if(!b) { 28 return a; 29 } 30 return gcd(b, a % b); 31 } 32 33 inline void add(int x) { 34 ans += bin[a[x]] << 1; 35 bin[a[x]]++; 36 return; 37 } 38 39 inline void del(int x) { 40 bin[a[x]]--;
41 ans -= bin[a[x]] << 1; 42 } 43 44 int main() { 45 int n, m; 46 scanf("%d%d", &n, &m); 47 int T = sqrt(n); 48 for(int i = 1; i <= n; i++) { 49 scanf("%d", &a[i]); 50 fr[i] = (i - 1) / T + 1; 51 } 52 for(int i = 1; i <= m; i++) { 53 ask[i].id = i; 54 scanf("%d%d", &ask[i].l, &ask[i].r); 55 } 56 std::sort(ask + 1, ask + m + 1); 57 58 int L = 1, R = 1; 59 bin[a[1]]++; 60 for(int i = 1; i <= m; i++) { 61 if(ask[i].l == ask[i].r) { 62 continue; 63 } 64 while(ask[i].l < L) { 65 add(--L); 66 } 67 while(R < ask[i].r) { 68 add(++R); 69 } 70 while(L < ask[i].l) { 71 del(L++); 72 } 73 while(ask[i].r < R) { 74 del(R--); 75 } 76 ask[i].ans = ans; 77 } 78 79 std::sort(ask + 1, ask + m + 1, cmp); 80 for(int i = 1; i <= m; i++) { 81 if(!ask[i].ans || ask[i].l == ask[i].r) { 82 puts("0/1"); 83 continue; 84 } 85 int g = gcd(ask[i].ans, 1ll * (ask[i].r - ask[i].l + 1) * (ask[i].r - ask[i].l)); 86 printf("%lld/%lld\n", ask[i].ans / g, 1ll * (ask[i].r - ask[i].l + 1) * (ask[i].r - ask[i].l) / g); 87 } 88 return 0; 89 }
AC程式碼