THE FIRST 莫队算法。
/************************************************************** Problem: 2038 User: keyboarder_zsq Language: C++ Result: Accepted Time:1644 ms Memory:2988 kb ****************************************************************/ //#include <bits/stdc++.h> #include<cstdio> #include<math.h> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; typedef pair<int,int> PII; const int N=5e4+10; struct asd{ LL a,b; int left,right; int id; }; int n,m,col[N],pos[N]; asd q[N]; bool cmp(asd x,asd y) { if(pos[x.left]==pos[y.left]) return x.right<y.right; return x.left<y.left; } bool cmp_id(asd x,asd y) { return x.id<y.id; } LL ans,num[N]; void update(int p,int add) { ans-=num[col[p]]*num[col[p]]; num[col[p]]+=add; ans+=num[col[p]]*num[col[p]]; } void solve() { memset(num,0,sizeof(num)); ans=0; for(int i=0,L=1,R=0;i<m;i++) { while(R<q[i].right) { update(R+1,1); R++; } while(R>q[i].right) { update(R,-1); R--; } while(L<q[i].left) { update(L,-1); L++; } while(L>q[i].left) { update(L-1,1); L--; } if(q[i].left==q[i].right) { q[i].a=0;q[i].b=1; continue; } q[i].a=ans-(q[i].right-q[i].left+1); q[i].b=(LL)(q[i].right-q[i].left+1)*(q[i].right-q[i].left); LL gcd=__gcd(q[i].a,q[i].b); q[i].a/=gcd; q[i].b/=gcd; } } int main() { scanf("%d%d",&n,&m); int block=(int)sqrt(n); for(int i=1;i<=n;i++) { scanf("%d",&col[i]); pos[i]=(i-1)/block+1; } for(int i=0;i<m;i++) { scanf("%d%d",&q[i].left,&q[i].right); q[i].id=i; } sort(q,q+m,cmp); solve(); sort(q,q+m,cmp_id); for(int i=0;i<m;i++) printf("%lld/%lld ",q[i].a,q[i].b); return 0; } /* 6 4 1 2 3 3 3 2 2 6 1 3 3 5 1 6 */