比較簡單的莫隊題,主要是爲了熟練板子。git
先考慮固定區間時咱們怎麼計算,假設區間\([l,r]\)內顏色爲\(i\)的襪子有\(cnt_i\)只,那麼對於顏色\(i\)來講,湊齊一雙的狀況個數爲:spa
最後咱們考慮全部顏色以及總狀況數,那麼此時湊出一雙的機率爲:code
\[\frac{\sum cnt_i\cdot(cnt_i-1)}{(r-l+1)\cdot(r-l-2)}\]it
首先仍是考慮如何快速地轉移區間,假設咱們已經求出了\([l,r]\)的貢獻(即上式的分母部分)\(ans\),那麼咱們考慮:io
而後就能夠\(O(1)\)轉移啦,剩下的就是莫隊基本操做了class
CODEgc
#include<cstdio> #include<cctype> #include<algorithm> #include<cmath> using namespace std; const int N=50005; struct data { int l,r,id; long long ans1,ans2; }q[N]; int n,m,L,R,a[N],cnt[N],blk[N],size; long long res; inline char tc(void) { static char fl[100000],*A=fl,*B=fl; return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++; } inline void read(int &x) { x=0; char ch; while (!isdigit(ch=tc())); while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); } inline void write(long long x) { if (x>9) write(x/10); putchar(x%10+'0'); } inline bool cmp1(data a,data b) { if (blk[a.l]==blk[b.l]) return blk[a.l]&1?a.r<b.r:a.r>b.r; return blk[a.l]<blk[b.l]; } inline bool cmp2(data a,data b) { return a.id<b.id; } inline void add(int col) { if (++cnt[col]>=2) res+=1LL*cnt[col]*(cnt[col]-1)-1LL*(cnt[col]-1)*(cnt[col]-2); } inline void del(int col) { if (--cnt[col]>=1) res+=1LL*cnt[col]*(cnt[col]-1)-1LL*cnt[col]*(cnt[col]+1); } inline long long gcd(long long n,long long m) { return m?gcd(m,n%m):n; } inline void divnum(long long a,long long b) { if (!a) { puts("0/1"); return; } long long d=gcd(a,b); a/=d; b/=d; write(a); putchar('/'); write(b); putchar('\n'); } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); register int i; read(n); read(m); size=sqrt(n); for (i=1;i<=n;++i) read(a[i]),blk[i]=(i-1)/size+1; for (i=1;i<=m;++i) read(q[i].l),read(q[i].r),q[i].id=i; sort(q+1,q+m+1,cmp1); L=q[1].l; R=q[1].r; for (i=L;i<=R;++i) add(a[i]); q[1].ans1=res; q[1].ans2=1LL*(R-L+1)*(R-L); for (i=2;i<=m;++i) { while (L<q[i].l) del(a[L++]); while (L>q[i].l) add(a[--L]); while (R>q[i].r) del(a[R--]); while (R<q[i].r) add(a[++R]); q[i].ans1=res; q[i].ans2=1LL*(q[i].r-q[i].l+1)*(q[i].r-q[i].l); } for (sort(q+1,q+m+1,cmp2),i=1;i<=m;++i) divnum(q[i].ans1,q[i].ans2); return 0; }