题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=2038

思路

选到同种颜色的概率为

i=1col(cnti2)(rl+12)

这样,知道了[L,R]的答案,我们可以O(1)得出[L±1,R][L,R±1]的答案,显然可以用莫队做。

代码

#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;
}