题意不说了,作为入门题/模板,在代码里解释一些细节问题
关于复杂度是O(n*sqrt(n)).其中,n和m为同一数量级. 证明自行百度
#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll c[N],num[N],p[N];
struct node{
ll l,r,id,fz,fm;
}q[N];
ll ans;
bool cmp1(node a,node b){
if(p[a.l]==p[b.l]) return a.r<b.r;
else return a.l<b.l;
}
bool cmp2(node a,node b){
return a.id < b.id;
}
void update(int pos,int flag){
ans-=num[c[pos]]*num[c[pos]];
num[c[pos]]+=flag;
ans+=num[c[pos]]*num[c[pos]];
return ;
}
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
ll n,m;
cin >>n>>m;
for(int i=1;i<=n;i++) cin >>c[i];
int t=sqrt(n);///分块的长度
for(int i=1;i<=n;i++) p[i]=(i-1)/t+1;
for(int i=1;i<=m;i++) cin >> q[i].l>>q[i].r,q[i].id=i;///给每个询问放入结构体
sort(q+1,q+1+m,cmp1);///根据莫队的算法来排序
ll l=1,r=0;///一开始是一个空区间,ans=0
for(int i=1;i<=m;i++){
///注意下更新的是哪一个点
while(r<q[i].r) update(r+1,1),r++;
while(r>q[i].r) update(r,-1),r--;
while(l<q[i].l) update(l,-1),l++;
while(l>q[i].l) update(l-1,1),l--;
q[i].fz=ans-(q[i].r-q[i].l+1);
q[i].fm=(q[i].r-q[i].l)*(q[i].r-q[i].l+1);
ll GCD=__gcd(q[i].fz,q[i].fm);
q[i].fz/=GCD;
q[i].fm/=GCD;
}
///排序按照id
sort(q+1,q+1+m,cmp2);
for(int i=1;i<=m;i++)
cout << q[i].fz <<"/"<<q[i].fm <<"\n";
return 0;
}