思路:
处理出块中每个位置跳出当前块的步数以及位置
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define DEBUG #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<long double, long double> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 2e5 + 10; int k[N], bl[N], nx[N], dp[N], blo, n; void init(int n) { blo = sqrt(n); for (int i = 1; i <= n; i++) bl[i] = (i-1)/blo + 1; for (int i = n; i >= 1; i--) { if(i + k[i] > n) { dp[i] = 1; nx[i] = i+k[i]; } else { int pos = i+k[i]; if(bl[pos] != bl[i]) { dp[i] = 1; nx[i] = i+k[i]; } else { dp[i] = dp[pos] + 1; nx[i] = nx[pos]; } } } } void update(int x, int y) { int id = bl[x]; k[x] = y; int l = (id-1)*blo+1, r = min(n, id*blo); for (int i = r; i >= l; i--) { if(i + k[i] > n) { dp[i] = 1; nx[i] = i+k[i]; } else { int pos = i+k[i]; if(bl[pos] != bl[i]) { dp[i] = 1; nx[i] = i+k[i]; } else { dp[i] = dp[pos] + 1; nx[i] = nx[pos]; } } } } int query(int x) { int ans = 0; while(x <= n) { ans += dp[x]; x = nx[x]; } return ans; } int main() { int op, x, y, m; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &k[i]); init(n); scanf("%d", &m); while(m--) { scanf("%d %d", &op, &x); x++; if(op == 1) { printf("%d ", query(x)); } else { scanf("%d", &y); update(x, y); } } return 0; }