CodeForces 103D

題意:給一個長度爲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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章