题意:在[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 ", ask[i].ans / g, 1ll * (ask[i].r - ask[i].l + 1) * (ask[i].r - ask[i].l) / g); 87 } 88 return 0; 89 }