CF797E Array Queries 题解
题意:
给定一个序列 \(a\),给定 \(T\) 组 \(p, k\),每次操作为 \(p = p + a_p + k\),问需要操作几次才能使得 \(p > n\)。
思路:
我们考虑根号分治。
模拟的时间复杂度为 \(\mathcal{O}(\frac{n}{k})\),如果全部数据按照模拟会超时。
我们设 \(dp_{i,j}\) 当 $p = i, k = j $ 时的答案,空间复杂度为 \(O(nk)\),会炸。
我们考虑将两种做法结合起来。
如果 \(k = \sqrt n\) 的时候,操作次数为 \(\sqrt n\)。当 \(k > \sqrt n\) 的时候,答案必定会小于 \(\sqrt n\)。 对于这部分我们直接模拟即可。
对于 \(k < \sqrt n\) 的这部分答案来说,我们可以用第二种办法提前预处理出来,询问时直接输出即可。
Ac code:
int dp[maxn >> 1][350], num, a[N];
signed main() {
int tests = 1; //tests = read();
while(tests--) {
int n = read(); num = sqrt(n);
for(int i = 1; i <= n; i++) a[i] = read();
int T = read();
for(int i = n; i >= 1; i--) {
for(int j = 1; j <= num; j++) {
if(a[i] + i + j > n) dp[i][j] = 1;
else dp[i][j] = dp[i + a[i] + j][j] + 1;
}
}
while(T--) {
int p = read(), k = read();
if(k <= num) printf("%d\n", dp[p][k]);
else {
int js = 0;
while(p <= n) {
js++, p = p + a[p] + k;
} printf("%d\n", js);
}
}
}
}
\[The\ End.
\]