题目链接
莫队 学习资源
计算公式很简单,化简一下后就是求一个区间的相同的数的个数的平方和,使用莫队算法,合理排序,暴力计算即可
flag[]数组统计每个数的出现次数,整体写法还是比较固定的,设计好del,add函数就可以
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define cl(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define gcd __gcd
const int maxn = 1<<20;
const LL inf =1LL<<50;
const LL mod1 = 1000000007;
int n,m;
int a[maxn];
int pos[maxn];
LL flag[maxn];
struct node{
int l,r,id;
}q[maxn];
bool cmp(node a,node b){
if(pos[a.l]==pos[b.l])return a.r<b.r;
else return pos[a.l]<pos[b.l];
}
int L,R;LL Ans;
void add(int x){
Ans-=flag[a[x]]*flag[a[x]];
flag[a[x]]++;
Ans+=flag[a[x]]*flag[a[x]];
}
void del(int x){
Ans-=flag[a[x]]*flag[a[x]];
flag[a[x]]--;
Ans+=flag[a[x]]*flag[a[x]];
}
LL ans[maxn];
LL ans2[maxn];
int main(){
while(~scanf("%d%d",&n,&m)){
int sz = sqrt(n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
pos[i]=i/sz;
}
for(int i=1;i<=m;i++){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1,q+1+m,cmp);
cl(flag,0);L=1;R=0;Ans=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){
R++;add(R);
}
while(R>q[i].r){
del(R);R--;
}
// cout<<q[i].l<<' '<<q[i].r<<' '<<Ans<<endl;
LL t = q[i].r-q[i].l+1;
LL A = Ans - t;
LL B = t * (t - 1);
LL tmp = gcd(A,B);
ans[q[i].id]=A/tmp;
ans2[q[i].id]=B/tmp;
}
for(int i=1;i<=m;i++){
printf("%lld/%lld\n",ans[i],ans2[i]);
}
}
return 0;
}