CodeForces 103D 分块处理

 

题目链接:http://codeforces.com/problemset/problem/103/D

题意:给定一个长度为n的序列。然后q个询问。每个询问为(a,b),表示从序列第a项开始每b项的加和。

思路:2014集训队论文中的<<根号算法——不只是分块>>中提到这题。 传统的数据结构比较擅长处理连续区间的询问。但是不擅长处理间隔位置的询问。考虑到分块。 对于b>sqrt(n)的询问。我们暴力计算。可以发现b越大我们扫描的位置就会越小。最大扫描次数为O(n/sqrt(n))。然后对于b<sqrt(n)的。我们离线处理。以b为关键字来分组。 询问中b相同的为一组。 然后用预存部分和来计算。 这样整体的时间复杂度为O(n*sqrt(n)).

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>  
#include<string.h>  
#include<cstring>
#include<algorithm>  
#include<queue>  
#include<math.h>  
#include<time.h>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
typedef long long int LL;
const int MAXN = 3*100000 + 10;
int block, n, q, a[MAXN];
LL ans[MAXN],sum[MAXN];
struct Query{ int id, pos; Query(int _id = 0, int _pos = 0) :id(_id), pos(_pos){} };
vector<Query>D[MAXN];
void init(){
    block = (int)sqrt(n + 0.5);
    for (int i = 1; i < MAXN; i++){
        if (D[i].empty()){ continue; }
        if (i > block){
            for (int j = 0; j < D[i].size(); j++){
                LL res = 0;
                for (int k = D[i][j].pos; k <= n; k += i){
                    res += a[k];
                }
                ans[D[i][j].id] = res;
            }
        }
        else{
            memset(sum, 0, sizeof(sum));
            for (int j = n; j > 0; j--){
                sum[j] = a[j]+(j+i<=n?sum[i+j]:0);
            }
            for (int j = 0; j < D[i].size(); j++){
                ans[D[i][j].id] = sum[D[i][j].pos];
            }
        }
        D[i].clear();
    }
}
int main(){
//#ifdef kirito
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//#endif
//    int start = clock();
    while (~scanf("%d", &n)){
        for (int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
        }
        scanf("%d", &q);
        for (int i = 1; i <= q; i++){ 
            int pos, d;  scanf("%d%d", &pos, &d);
            D[d].push_back(Query(i, pos)); //相同d的为一组
        }
        init();
        for (int i = 1; i <= q; i++){
            printf("%lld\n", ans[i]);
        }
    }
//#ifdef LOCAL_TIME
//    cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
    return 0;
}

 

posted @ 2016-10-06 11:51  キリト  阅读(410)  评论(0编辑  收藏  举报