思路:
裸的莫队,注意有一点小的组合数学的知识
#include<bits/stdc++.h>
using namespace std;
#define sf scanf
#define int long long
const int maxn=5e4+10;
int col[maxn],amt[maxn],b[maxn],n,m,k,c[maxn][5];
typedef pair<int,int> T;
T ret[maxn];
struct pi{
int l,r,id;
bool operator <(const pi &t) const{
return (b[l]<b[t.l]||(b[l]==b[t.l])&&r<t.r);
}
}p[maxn];
inline void pre(){
c[0][0]=1;
for(int i=1;i<=n;++i){
c[i][0]=1;
for(int j=1;j<=2;++j){
c[i][j]=c[i-1][j-1]+c[i-1][j];
}
}
}
inline int gcd(int a,int b){
int c;
while(b){
c=b;b=a%b;a=c;
}
return a;
}
signed main(){
sf("%lld%lld",&n,&m);k=sqrt(n);
pre();
for(int i=1;i<=n;++i)sf("%lld",&col[i]),b[i]=(i-1)/k+1;
for(int i=1;i<=m;++i)sf("%lld%lld",&p[i].l,&p[i].r),p[i].id=i;
sort(p+1,p+m+1);
int l=0,r=0,up=0,down=0;amt[0]=1;
for(int i=1;i<=m;++i){
while(r<p[i].r){
++r;++amt[col[r]];
up+=c[amt[col[r]]-1][1];
}
while(l<p[i].l){
--amt[col[l]];
up-=c[amt[col[l]]][1];
++l;
}
while(l>p[i].l){
--l;++amt[col[l]];
up+=c[amt[col[l]]-1][1];
}
while(r>p[i].r){
--amt[col[r]];
up-=c[amt[col[r]]][1];
--r;
}
if(up==0)ret[p[i].id]=make_pair(0,1);
else{
down=c[(r-l+1)][2];int q=gcd(down,up);
ret[p[i].id]=make_pair(up/q,down/q);
}
}
for(int i=1;i<=m;++i)printf("%lld/%lld\n",ret[i].first,ret[i].second);
return 0;
}