Description
小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。
【题目分析】
分块
【代码】
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,k;
struct line{
int l,r,num;
}b[50001];
int c[50001],a[50001],L[501],R[501],cnt,T;
long long ans[50001];
inline bool cmp1(line a,line b)
{return a.l<b.l;}
inline bool cmp2(line a,line b)
{return a.r<b.r;}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
for (int i=1;i<=m;++i)
{
scanf("%d%d",&b[i].l,&b[i].r);
if (b[i].l>b[i].r) swap(b[i].l,b[i].r);
b[i].num=i;
}
sort(b+1,b+m+1,cmp1);
T=sqrt(m);
for (int i=1;i<=n;i+=T)
{
++cnt;
L[cnt]=i;
R[cnt]=i+T-1;
}
R[cnt]=n;
for (int i=1;i<=cnt;++i) sort(b+L[i],b+R[i]+1,cmp2);
int l=1,r=0; long long tmp=0;
for (int i=1;i<=m;++i)
{
// printf("%d %d\n",b[i].l,b[i].r);
while (r<b[i].r)
{
r++;
tmp-=c[a[r]]*c[a[r]];
c[a[r]]++;
tmp+=c[a[r]]*c[a[r]];
}
while (l>b[i].l)
{
l--;
tmp-=c[a[l]]*c[a[l]];
c[a[l]]++;
tmp+=c[a[l]]*c[a[l]];
}
while (r>b[i].r)
{
tmp-=c[a[r]]*c[a[r]];
c[a[r]]--;
tmp+=c[a[r]]*c[a[r]];
r--;
}
while (l<b[i].l)
{
tmp-=c[a[l]]*c[a[l]];
c[a[l]]--;
tmp+=c[a[l]]*c[a[l]];
l++;
}
ans[b[i].num]=tmp;
}
for (int i=1;i<=m;++i) printf("%lld\n",ans[i]);
}