比较简单的莫队题,主要是为了熟练板子。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; }