题目:点击此处
莫队板子,add,和remove的时候,每增减一个数字的次数就计算一次结果,
比如加了一个数的次数,那answer+=ks*ks*s 同时减掉之前的 即answer-=(ks-1)*(ks-1)*s
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#define ll long long
const int maxn=320010;
const int Block=555;
const int tt=1;
using namespace std;
struct node
{
int id;
int l,r;
}pos[1000010];
int n,q,l,r;
ll answer=0,ans[1000010],cnt[1000010],a[maxn];
bool cmp(node a,node b)
{
if(a.l/Block!=b.l/Block)
return a.l/Block<b.l/Block;
return a.r<b.r;
}
void add(int positoin)
{
cnt[a[positoin]]++;
answer+=cnt[a[positoin]]*cnt[a[positoin]]*a[positoin];
answer-=(cnt[a[positoin]]-1)*(cnt[a[positoin]]-1)*a[positoin];
}
void Remove(int positoin)
{
cnt[a[positoin]]--;
answer+=cnt[a[positoin]]*cnt[a[positoin]]*a[positoin];
answer-=(cnt[a[positoin]]+1)*(cnt[a[positoin]]+1)*a[positoin];
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=0;i<n;i++)
{
scanf("%I64d",&a[i]);
}
for(int i=0;i<q;i++)
{
scanf("%d %d",&pos[i].l,&pos[i].r);
pos[i].l--;pos[i].r--;
pos[i].id=i;
}
sort(pos,pos+q,cmp);
int cl=0,cr=0;
for(int i=0;i<q;i++)
{
l=pos[i].l;r=pos[i].r;
//cout<<l<<" "<<r<<endl;
while(cl<l) {
Remove(cl);
cl++;
}
while(cl>l) {
add(cl-1);
cl--;
}
while(cr<=r) {
add(cr);
cr++;
}
while(cr>r+1)
{
Remove(cr-1);
cr--;
}
ans[pos[i].id]=answer;
}
for(int i=0;i<q;i++)
printf("%I64d\n",ans[i]);
return 0;
}