发现这道题没有修改,并且可以离线,于是可以考虑莫队。
那么具体这么做?很容易发现答案就是这个区间所有颜色个数 (d_i*(d_i-1)) 的和再除以 (r-l) 和 (r-l-1) 即可。
于是我们莫队只需要维护一下分子的平方项,另外一个我们可以直接得到:(sum_{i=1}^{n}{d_i}=r-l+1) 。
那么最后直接约分即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100005,M=1000005;
#define ll long long
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-'){f=-1;}ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int a[N],pos[N],n,m;
ll ANS[N][2],ans,cnt[N];
struct node{
int l,r,id;
}q[N];
inline bool cmp(node x,node y){
if(pos[x.l]==pos[y.l]) return x.r<y.r;
return pos[x.l]<pos[y.l];
}
inline void update(int id,int f){
int x=a[id];
ans-=cnt[x]*(cnt[x]-1);
cnt[a[id]]+=f;
ans+=cnt[x]*(cnt[x]-1);
return ;
}
int main(){
n=read(),m=read();
int op=sqrt(n);
for(int i=1;i<=n;i++){
a[i]=read();
pos[i]=i/op;
}
for(int i=1;i<=m;i++){
q[i].l=read(),q[i].r=read(),q[i].id=i;
}
sort(q+1,q+m+1,cmp);
for(int i=1,l=1,r=0;i<=m;i++){
while(l<q[i].l) update(l++,-1);
while(l>q[i].l) update(--l,1);
while(r<q[i].r) update(++r,1);
while(r>q[i].r) update(r--,-1);
if(q[i].l==q[i].r){
ANS[q[i].id][0]=0;
ANS[q[i].id][1]=1;
continue;
}
ll len=q[i].r-q[i].l+1;
ll d=__gcd(ans,len*(len-1));
ANS[q[i].id][0]=ans/d;
ANS[q[i].id][1]=len*(len-1)/d;
}
for(int i=1;i<=m;i++) printf("%lld/%lld
",ANS[i][0],ANS[i][1]);
return 0;
}