http://www.lydsy.com/JudgeOnline/problem.php?id=2038
分析:
推荐一篇莫队算法讲解的博客:点击打开链接
AC代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include<list>
#include <bitset>
#include <climits>
#include <algorithm>
#define mset(a,n) memset(a,n,sizeof(a))
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
typedef long long LL;
const LL mod=1e9+7;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
using namespace std;
const int N=50005;
LL a[N];
LL pos[N];
LL temp[N];
LL ans;
struct node{
LL l;
LL r;
LL index;
LL a,b;
}Q[N];
bool cmp1(node x,node y){
return pos[x.l]==pos[y.l]?x.r<y.r:x.l<y.l;
}
bool cmp2(node x,node y){
return x.index<y.index;
}
void mdy(int i,int add){
ans+=(LL)(2*add*temp[a[i]]+1);
temp[a[i]]+=add;
}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int main (){
LL n,m;
scanf ("%lld%lld",&n,&m);
int div=(int)sqrt(n*1.0);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]),pos[i]=(i-1)/div+1;// i 在第pos[i]块
for (int i=1;i<=m;i++){
scanf ("%lld%lld",&Q[i].l,&Q[i].r);
Q[i].index=i;
}
sort(Q+1,Q+m+1,cmp1);// 分块后的排序
int ll=1,rr=0;
ans=0;
for (int i=1;i<=m;i++){
while (rr<Q[i].r) rr++,mdy(rr,1);
while (rr>Q[i].r) mdy(rr,-1),rr--;
while (ll<Q[i].l) mdy(ll,-1),ll++;
while (ll>Q[i].l) ll--,mdy(ll,1);
if (Q[i].l==Q[i].r){
Q[i].a=0;Q[i].b=1;
continue;
}
Q[i].a=ans-(Q[i].r-Q[i].l+1);
Q[i].b=(LL)((Q[i].r-Q[i].l+1)*(Q[i].r-Q[i].l));
LL k=gcd(Q[i].a,Q[i].b);
Q[i].a/=k;Q[i].b/=k;
}
sort(Q+1,Q+m+1,cmp2);// 找回原序列
for (int i=1;i<=m;i++) printf("%lld/%lld\n",Q[i].a,Q[i].b);
return 0;
}