初次学习。具体参考这篇文章ORZ,莫队算法第一题。
#include<bits/stdc++.h>
#define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end(); ++it)
using namespace std;
typedef long long ll;
const int maxn = 50000 + 5;
int color[maxn],cnt[maxn],pos[maxn];
struct Node
{
int l,r,id;
bool operator < (const Node & rhs) const {
if(pos[l]==pos[rhs.l]) return r < rhs.r;
return pos[l] < pos[rhs.l];
}
};
Node Q[maxn];
ll res[maxn][2],ans;
void Modify(int col,int d)
{
ans -= (ll)cnt[col]*cnt[col];
cnt[col] += d;
ans += (ll)cnt[col]*cnt[col];
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)) {
for(int i = 1; i <= n; i++) {
int x;
scanf("%d",&x);
color[i] = x;
cnt[x] = 0;
}
int bk = sqrt(n);
for(int i = 0; i < m; i++) {
scanf("%d%d",&Q[i].l,&Q[i].r);
Q[i].id = i;
pos[Q[i].l] = Q[i].l/bk;
}
sort(Q,Q+m);
int ql = 1,qr = 0;
ans = 0;
for(int i = 0; i < m; i++) {
int ID = Q[i].id,L = Q[i].l,R = Q[i].r;
if(L==R) {
res[ID][0] = 0;
res[ID][1] = 1;
continue;
}
if(qr<R) {
for(int j = qr+1; j <= R; j++) Modify(color[j],1);
}else {
for(int j = qr; j > R; j--) Modify(color[j],-1);
}
if(ql>L) {
for(int j = ql-1; j >= L; j--) Modify(color[j],1);
}else {
for(int j = ql; j < L; j++) Modify(color[j],-1);
}
ql = L;qr = R;
if(!ans) {
res[ID][0] = 0;
res[ID][1] = 1;
}else {
ll a = ans - (R-L+1);
ll b = ((ll)R-L+1)*(R-L);
ll t = __gcd(a,b);
res[ID][0] = a/t;
res[ID][1] = b/t;
}
}
for(int i = 0; i < m; i++) {
printf("%lld/%lld\n",res[i][0],res[i][1]);
}
}
return 0;
}