CF 86D
题目链接:
http://codeforces.com/problemset/problem/86/D
题意:
一个数列,问[L,R]区间内(每个数字的个数的平方*数字的大小)的和。
思路:
莫队模板。
不过更新的时候卡常数闹哪样……从网上抄了一个,好像移位运算比单纯乘法快很多的样子,也mark一下好了
源码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
const int MAXN = 200000 + 5;
int blocksize;
int pos[MAXN];
struct Q
{
int l, r;
int id;
}q[MAXN];
bool cmp(Q a, Q b)
{
if(pos[a.l] == pos[b.l]) return a.r < b.r;
return a.l < b.l;
}
int data[MAXN];
LL num[MAXN * 5];
LL res[MAXN];
int n, m;
void update(int u, int v, LL &ans)
{
if(v == 1){
ans += ((num[u] << 1) + 1) * u; ///网上抄的
num[u]++;
}
else{
num[u]--;
ans -= ((num[u] << 1) + 1) * u;
}
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF){
blocksize = sqrt(1.0 * n);
for(int i = 1 ; i <= n ; i++){
scanf("%d", &data[i]);
pos[i] = (i - 1) / blocksize;
}
for(int i = 0 ; i < m ; i++){
scanf("%d%d", &q[i].l, &q[i].r);
q[i].id = i;
}
sort(q, q + m, cmp);
int curr = 0, curl = 1;
LL cnt = 0;
memset(num, 0, sizeof(num));
for(int i = 0 ; i < m ; i++){
if(q[i].l == q[i].r){
res[q[i].id] = data[q[i].l];
continue;
}
for(int j = curr + 1 ; j <= q[i].r ; j++) update(data[j], 1, cnt);
for(int j = curr ; j > q[i].r ; j--) update(data[j], -1, cnt);
for(int j = curl ; j < q[i].l ; j++) update(data[j], -1, cnt);
for(int j = curl - 1; j >= q[i].l ; j--) update(data[j], 1, cnt);
curr = q[i].r;
curl = q[i].l;
res[q[i].id] = cnt;
// printf("i = %d, l = %d, r = %d, ans = %I64d\n", i, q[i].l, q[i].r, cnt);
}
for(int i = 0 ; i < m ; i++) printf("%I64d\n", res[i]);
}
return 0;
}