CF 86D 莫队(卡常数)

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;
}

你可能感兴趣的:(CF 86D 莫队(卡常数))