先预处理一下C(i,2),然后增区间的时候只需要执行减加操作。
#include<bits/stdc++.h>
using namespace std;
#define clr(x,y) memset(x,y,sizeof x)
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + 10;
int a[maxn],num[maxn],pos[maxn];
struct Node{int L,R,id;}q[maxn];
bool cmp(Node p1,Node p2)
{
return pos[p1.L] == pos[p2.L] ? p1.R < p2.R : pos[p1.L] < pos[p2.L];
}
ll C[maxn];
void Init()
{
for(int i = 0; i < maxn; i ++)
{
if(i < 2)C[i] = 0;
else C[i] = 1ll *i * (i - 1) / 2;
}
}
ll Ans = 0;
ll ans1[maxn],ans2[maxn];
void add(int pos)
{
num[a[pos]] ++;
Ans = Ans - C[num[a[pos]] - 1] + C[num[a[pos]]];
}
void del(int pos)
{
num[a[pos]] --;
Ans = Ans - C[num[a[pos]] + 1] + C[num[a[pos]]];
}
ll gcd(ll x,ll y)
{
return y ? gcd(y,x % y) : x;
}
int main()
{
int n,m;
while( ~ scanf("%d%d",&n,&m))
{
Init();Ans = 0;clr(num,0);
int ss = sqrt(n);
for(int i = 1; i <= n;i ++)scanf("%d",&a[i]),pos[i] = i / ss;
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,cmp);
int l = 1,r = 0;
for(int i = 1; i <= m;i ++)
{
while(l < q[i].L)
{
del(l);l ++;
}
while(l > q[i].L)
{
l --;
add(l);
}
while(r > q[i].R)
{
del(r);r --;
}
while(r < q[i].R)
{
r ++;add(r);
}
ll t1 = Ans,t2 = C[q[i].R - q[i].L + 1];
ll d = gcd(t1,t2);if(d == 0)d = 1;
ans1[q[i].id] = t1/d;ans2[q[i].id] = t2/d;
}
for(int i = 1; i <= m;i ++)
printf("%lld/%lld\n",ans1[i],ans2[i]);
}
return 0;
}