題意:給一個長度爲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;
}