现在的位置: 首页 > 综合 > 正文

CodeForces 103D

2013年10月20日 ⁄ 综合 ⁄ 共 1086字 ⁄ 字号 评论关闭

题意:给一个长度为n的数组,进行p次询问。每次询问输入两个数a,b,输出数组中第a位开始,每隔b位的所有数字之和。(1<=n,p<=3*10^5)

解法:刚看清题意,一直在考虑是不是有什么特殊的数据结构,可以把每次查询的时间复杂度降到O(logn)。但其实仔细分析可以发现如果b>=600,那每次查询最多只需要取500个数字。如果测试数据b都大于600,那么时间复杂度是O(500*p),可以在限定时间内完成。就是说如果b>=600,我们只需要直接计算就好了。如果b<600,我们可以离线查询。对每一组b相同的查询,我们只需要O(n)的时间就能完成。所以这一步的时间复杂度是O(600*n)。总时间复杂度是O(500*p+600*n)。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <memory.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <iostream>
#define lint __int64
using namespace std;

const int N = 300005;
const int M = 600;

vector< pair<int, int> > V[M];
int mass[N];
lint sum[N], res[N];

int main() {
    int n, m, a, b, i, j;
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
        scanf("%d", mass + i);
    scanf("%d", &m);
    for (i = 0; i < M; i++) V[i].clear();
    for (i = 1; i <= m; i++) {
        scanf("%d %d", &a, &b);
        if (b >= M) {
            res[i] = 0;
            for (j = a; j <= n; j += b)
                res[i] += mass[j];
        } else {
            V[b].push_back(make_pair(i, a));
        }
    }
    for (i = 1; i < M; i++) {
        if (!V[i].empty()) {
            for (j = n; j >= 1; j--) {
                sum[j] = mass[j];
                if (i + j <= n)
                    sum[j] += sum[j+i];
            }
            for (j = 0; j < V[i].size(); j++) {
                res[V[i][j].first] = sum[V[i][j].second];
            }
        }
    }
    for (i = 1; i <= m; i++)
        printf("%I64d\n", res[i]);
    return 0;
}

抱歉!评论已关闭.