题意:
题意:给出一个
n
n
n个数组成的数列
a
a
a,有
t
t
t次询问,每次询问为一个
[
l
,
r
]
[l,r]
[l,r]的区间,求区间内每种数字出现次数的平方×数字的值的和。
n
,
t
<
=
2
e
5
,
a
i
<
=
1
e
6
n,t<=2e5,a_i<=1e6
n,t<=2e5,ai<=1e6。
题解:
就是个莫队裸题吧。开个桶记录当前每个数出现的次数,考虑加进来一个数和删掉一个数的影响都很好算,就用
(
x
+
1
)
2
−
x
2
(x+1)^2-x^2
(x+1)2−x2算出加一时的增加量,再乘
a
i
a_i
ai就好了。减去一个数的话也差不多。就做完了。
代码:
#include <bits/stdc++.h>
using namespace std;
int n,t,l=1,r,pos[200010],sz;
long long res,ans[200010],book[1000010],a[200010];
struct node
{
int l,r,id;
}q[200010];
inline int read()
{
int x=0;
char s=getchar();
while(s>'9'||s<'0')
s=getchar();
while(s>='0'&&s<='9')
{
x=x*10+s-'0';
s=getchar();
}
return x;
}
inline int cmp(node x,node y)
{
if(pos[x.l]!=pos[y.l])
return pos[x.l]<pos[y.l];
return x.r<y.r;
}
inline void add(int x)
{
res+=(2*book[a[x]]+1)*a[x];
book[a[x]]++;
}
inline void del(int x)
{
res-=(2*book[a[x]]-1)*a[x];
book[a[x]]--;
}
int main()
{
n=read();
t=read();
sz=sqrt(n);
for(int i=1;i<=n;++i)
{
a[i]=read();
pos[i]=(i-1)/sz+1;
}
for(int i=1;i<=t;++i)
{
q[i].l=read();
q[i].r=read();
q[i].id=i;
}
sort(q+1,q+t+1,cmp);
for(int i=1;i<=t;++i)
{
while(r<q[i].r)
add(++r);
while(r>q[i].r)
del(r--);
while(l>q[i].l)
add(--l);
while(l<q[i].l)
del(l++);
ans[q[i].id]=res;
}
for(int i=1;i<=t;++i)
printf("%I64d\n",ans[i]);
return 0;
}