题目链接:http://codeforces.com/problemset/problem/86/D
题目大意:给定一个数组,每次询问一个区间[l,r],设cnt[i]为数字i在该区间内的出现次数,求该区间内所有的cnt[i]^2*i。
解题思路:莫队模板题,改一下add,remove就好了。
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=2e5+;
const int MAX=1e6+;
int cnt[MAX],arr[N],unit;
ll power,res[N]; struct node{
int l,r;
int id;
}q[N]; void add(int pos){
power=power+(ll)arr[pos]*(cnt[arr[pos]]<<|);//(a+1)*(a+1)=a*a+2*a+1;
cnt[arr[pos]]++;
} void remove(int pos){
power=power-(ll)arr[pos]*(cnt[arr[pos]]<<-);
cnt[arr[pos]]--;
} bool cmp(node a,node b){
return a.l/unit!=b.l/unit?a.l/unit<b.l/unit:a.r<b.r;
} int main(){
int n,m;
scanf("%d%d",&n,&m);
unit=sqrt(n);
for(int i=;i<=n;i++){
scanf("%d",&arr[i]);
}
for(int i=;i<=m;i++){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+,q++m,cmp); int L=q[].l,R=L-;
for(int i=;i<=m;i++){
while(L>q[i].l)
add(--L);
while(L<q[i].l)
remove(L++);
while(R<q[i].r)
add(++R);
while(R>q[i].r)
remove(R--);
res[q[i].id]=power;
}
for(int i=;i<=m;i++){
printf("%I64d\n",res[i]);
}
}