\(\text{Solution}\)
一道莫队比较模板的题,对于每一次变化加减一个组合数即可,组合数预处理。
\(\text{Code}\)
#include<cstdio>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
const int N = 5e4 + 5;
int n,m,a[N],d[N],bl; LL res,c[N];
struct nd{int l,r,id;}b[N];
struct ANS{LL q,p;}ans[N];
bool cmp(nd x,nd y){
return ((x.l / bl) ^ (y.l / bl) ? x.l < y.l : (((x.l / bl) & 1) ? x.r < y.r : x.r > y.r));
}
void Add(int x,int v){res -= c[d[x]],d[x] += v,res += c[d[x]];}
LL gcd(LL x,LL y){return y == 0 ? x : gcd(y,x % y);}
int main()
{
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; i++) scanf("%d",&a[i]);
for (int i = 2; i <= n; i++) c[i] = (LL)i * (i - 1) / 2LL;
for (int i = 1; i <= m; i++) scanf("%d%d",&b[i].l,&b[i].r),b[i].id = i;
bl = n / sqrt(m * 2 / 3),sort(b + 1,b + 1 + m,cmp),res = 0;
for (int i = 1,L = 1,R = 0; i <= m; i++)
{
if (b[i].l == b[i].r) {ans[b[i].id] = ANS{0,1}; continue;}
while (R < b[i].r) R++,Add(a[R],1);
while (L > b[i].l) L--,Add(a[L],1);
while (R > b[i].r) Add(a[R],-1),R--;
while (L < b[i].l) Add(a[L],-1),L++;
int len = b[i].r - b[i].l + 1; LL g = gcd(c[len],res);
ans[b[i].id] = ANS{res / g,c[len] / g};
}
for (int i = 1; i <= m; i++) printf("%lld/%lld\n",ans[i].q,ans[i].p);
}