我们只需将序列分成 nsqrt{n}n 块,对于每一个点维护一个 val[i]val[i]val[i],to[i]to[i]to[i],分别代表该点跳到下一个块所需要的代价以及会跳到的节点编号。在查询时,我们最多会跳 nsqrt{n}n 块,修改的时候将节点所在区间暴力修改即可。
Code:
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn = 2000000 + 3; int arr[maxn], n, block, to[maxn], val[maxn], m, belong[maxn]; struct Data_Structure{ inline void init(){ block = sqrt(n); for(int i = n;i >= 1; --i) { belong[i] = (i - 1) / block + 1; to[i] = belong[i + arr[i]] == belong[i] ? to[i + arr[i]] : i + arr[i]; val[i] = belong[i + arr[i]] == belong[i] ? val[i + arr[i]] + 1 : 1; } } inline int solve(){ int pos, ans = 0; scanf("%d",&pos); ++pos; while(pos <= n){ ans += val[pos]; pos = to[pos]; } return ans; } inline void update(){ int pos, data; scanf("%d%d",&pos,&data); ++pos; arr[pos] = data; for(int i = min(belong[pos] * block, n); i >= (belong[pos] - 1) * block + 1; --i) { to[i] = belong[i + arr[i]] == belong[i] ? to[i + arr[i]] : i + arr[i]; val[i] = belong[i + arr[i]] == belong[i] ? val[i + arr[i]] + 1 : 1; } } }T; int main(){ scanf("%d",&n); for(int i = 1;i <= n; ++i) scanf("%d",&arr[i]); T.init(); scanf("%d",&m); while(m--) { int opt; scanf("%d",&opt); switch(opt) { case 1: { printf("%d ", T.solve()); break; } case 2: { T.update(); break; } } } return 0; }