题目链接:点击打开链接
题意:给定一个数组,每次询问一个区间[l,r],设cnt[i]为数字i在该区间内的出现次数,求该区间内所有的cnt[i]^2*i。
思路:区间离线不修改只查询问题,用莫队算法。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define ll long long
const int N = 2e5+5;
int a[N],n,t,bk,cnt[5*N];
ll res,ans[N];
struct Q{
int l,r,id;
}q[N];
bool cmp(Q a,Q b){
if(a.l/bk==b.l/bk) return a.r<b.r;
return a.l/bk<b.l/bk;
}
void add(int x){
cnt[a[x]]++;
res+=a[x]*(2*cnt[a[x]]-1);
}
void del(int x){
cnt[a[x]]--;
res-=a[x]*(2*cnt[a[x]]+1);
}
int main(){
while(~scanf("%d%d",&n,&t)){
memset(cnt,0,sizeof(cnt));
res=0;
bk=sqrt(n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=t;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
sort(q+1,q+t+1,cmp);
int L=1,R=0;
for(int i=1;i<=t;i++){
while(L<q[i].l){
del(L);
L++;
}
while(L>q[i].l){
L--;
add(L);
}
while(R<q[i].r){
R++;
add(R);
}
while(R>q[i].r){
del(R);
R--;
}
ans[q[i].id]=res;
}
for(int i=1;i<=t;i++) cout<<ans[i]<<endl;
}
}