牛客小白月赛17-G区间求和(莫队)
题目链接:https://ac.nowcoder.com/acm/contest/1085/G
题意: 给你n个数,每个数为$a_i$,现在有m个询问,每个询问l,r,需要求出:∑ i = l r a i ∗ n u m ( a [ i ] ) \sum_{i=l}^{r}a_i*num(a[i]) i=l∑rai∗num(a[i])
n u m ( a [ i ] ) num(a[i]) num(a[i])为 a i a_i ai在这个区间中出现的次数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,m,b[N];
ll ans[N],cnt[N],res;
struct node{
int l,r,id,pos;
bool operator < (const node &b)const {
if(pos==b.pos)return r<b.r;
else return pos<b.pos;
}
}a[N];
void add(int x)
{
res-=1ll*b[x]*cnt[b[x]]*cnt[b[x]];
cnt[b[x]]++;
res+=1ll*b[x]*cnt[b[x]]*cnt[b[x]];
}
void del(int x)
{
res-=1ll*b[x]*cnt[b[x]]*cnt[b[x]];
cnt[b[x]]--;
res+=1ll*b[x]*cnt[b[x]]*cnt[b[x]];
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
int block=sqrt(n);
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=m;i++){
cin>>a[i].l>>a[i].r;
a[i].id=i;
a[i].pos=a[i].l/block;
}
sort(a+1,a+1+m);
int l=a[1].l,r=a[1].l-1;
for(int i=1;i<=m;i++){
while(l<a[i].l)del(l++);
while(l>a[i].l)add(--l);
while(r<a[i].r)add(++r);
while(r>a[i].r)del(r--);
ans[a[i].id]=res;
}
for(int i=1;i<=m;i++){
cout<<ans[i]<<endl;
}
return 0;
}