solution:对于每个点,我们记录两个值:1.它要跳几次才能跳出它所在的块。2.它跳出块以后跳到哪里。这样,我们就可以o(sqr(n))地修改和查询了
#include <cmath>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 200005
#define ll long long
int a[N], cn[N], cp[N], bl[N];
int cnt , blk, n, m;
inline int Read () {
int x = 0 , f = 1 ;
char ch = getchar () ;
while ( ! isdigit ( ch ) ) {
if ( ch == '-' ) f = -1 ;
ch = getchar () ;
}
while ( isdigit ( ch ) ) {
x = x * 10 + ch - '0' ;
ch = getchar () ;
}
return x * f ;
}
int calc( int x ){
int tmp = 0;
for ( ;; ){
tmp += cn[x];
if ( !cp[x] ) break;
x = cp[x];
}
return tmp;
}
int main(){
n = read();
for ( int i = 1; i <= n; i++) a[i] = read();
blk = sqrt(n);
if ( n % blk ) cnt = n / blk + 1 ;
else cnt = n / blk;
for ( int i = 1; i <= n; i++) bl[i] = (i-1)/blk + 1;
for ( int i = n; i >= 1; i-- ){
if ( i + a[i] > n ) cn[i] = 1;
else if ( bl[i] == bl[i+a[i]] ) cn[i] = cn[i+a[i]]+1, cp[i] = cp[i+a[i]];
else cn[i] = 1, cp[i] = i+a[i];
}
m = read();
while ( m-- ){
int x, y, z;
x = Read () , y = Read () , ++ y ;
if ( x == 1 ){
printf( "%d\n", calc(y));
}else {
z = read();a[y] = z;
for ( int i = y; i >= (bl[y]-1)*blk +1; i-- ){
if ( bl[i] == bl[i+a[i]] )
cn[i] = cn[i+a[i]]+1, cp[i] = cp[i+a[i]];
else cn[i] = 1, cp[i] = i+a[i];
}
}
}
return 0;
}