传送门biu~
莫队裸题,是莫涛在论文中提到的经典题目。【莫队(带修改)模板点这里】
用莫队维护在区间[l,r]中选择相同颜色的袜子的方案数。对于每个询问,分子为莫队中维护的方案数,分母为在区间[l,r]中选择两只袜子共有多少种选择方案。
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long ans;
int a[50005],sum[50005],block[50005];
struct Ques{int l,r,id;long long a,b;}q[50005];
bool cmp1(Ques a,Ques b){return block[a.l]<block[b.l] || block[a.l]==block[b.l] && a.r<b.r;}
bool cmp2(Ques a,Ques b){return a.id<b.id;}
inline void update(int x,int opt){
ans-=1ll*sum[a[x]]*(sum[a[x]]-1);
sum[a[x]]+=opt;
ans+=1ll*sum[a[x]]*(sum[a[x]]-1);
}
int main(){
scanf("%d%d",&n,&m);
int blocksiz=sqrt(n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
block[i]=(i-1)/blocksiz+1;
}
for(int i=1;i<=m;++i) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
sort(q+1,q+m+1,cmp1);
int L=1,R=0;
for(int i=1;i<=m;++i){
while(R<q[i].r) update(++R,1);
while(R>q[i].r) update(R--,-1);
while(L>q[i].l) update(--L,1);
while(L<q[i].l) update(L++,-1);
q[i].a=ans;q[i].b=1ll*(q[i].r-q[i].l+1)*(q[i].r-q[i].l);
long long G=__gcd(q[i].a,q[i].b);
q[i].a/=G;q[i].b/=G;
}
sort(q+1,q+m+1,cmp2);
for(int i=1;i<=m;++i) printf("%lld/%lld\n",q[i].a,q[i].b);
return 0;
}