题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=2038
思路
选到同种颜色的概率为
这样,知道了的答案,我们可以得出和的答案,显然可以用莫队做。
代码
#include <cstdio>
#include <algorithm>
#include <cmath>
const int maxn=50000;
struct query
{
int l,r,id;
};
struct frac
{
long long z,m;
frac(int z_=0,int m_=0)
{
z=z_;
m=m_;
}
};
long long cnt[maxn+10],nowans;
int n,c[maxn+10],m,tot,belong[maxn+10],nowl,nowr;
query q[maxn+10];
frac ans[maxn+10];
long long gcd(long long a,long long b)
{
return b?gcd(b,a%b):a;
}
bool cmp(const query &a,const query &b)
{
return (belong[a.l]==belong[b.l])?(a.r<b.r):(belong[a.l]<belong[b.l]);
}
inline int updata(int x,int op)
{
nowans-=cnt[c[x]]*cnt[c[x]];
cnt[c[x]]+=op;
nowans+=cnt[c[x]]*cnt[c[x]];
return 0;
}
inline int solve(int x)
{
while(nowr<q[x].r)
{
updata(++nowr,1);
}
while(nowr>q[x].r)
{
updata(nowr--,-1);
}
while(nowl<q[x].l)
{
updata(nowl++,-1);
}
while(nowl>q[x].l)
{
updata(--nowl,1);
}
ans[q[x].id].z=nowans-(nowr-nowl+1);
ans[q[x].id].m=1ll*(nowr-nowl+1)*(nowr-nowl);
long long g=gcd(ans[q[x].id].m,ans[q[x].id].z);
if(g==0)
{
ans[q[x].id].m=1;
}
else
{
ans[q[x].id].z/=g;
ans[q[x].id].m/=g;
}
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(register int i=1; i<=n; ++i)
{
scanf("%d",&c[i]);
}
for(register int i=1; i<=m; ++i)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
int size=(int)sqrt(m);
for(register int i=1; i<=m; ++i)
{
belong[i]=(i-1)/size+1;
}
std::sort(q+1,q+m+1,cmp);
nowl=1;
nowr=0;
for(register int i=1; i<=m; ++i)
{
solve(i);
}
for(register int i=1; i<=m; ++i)
{
printf("%lld/%lld\n",ans[i].z,ans[i].m);
}
return 0;
}