分块做法。
因为写的是LCT所以这个思路只是大概了解了一下。
十分脚妙。(23333/斜眼笑)
蒯来的代码,不谢~orz
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
int n,m;
int bl[200011], f[200011], to[200011];
int k[200011];
void init(){
scanf("%d", &n);
int sq, r;
//???
sq = int(sqrt(n));
int o = sq, t = 0;
for(int i = 0; i < n; i++){
if(o == sq){
bl[i] = ++t;
o = 1;
}
else bl[i] = t, o++;
scanf("%d", &f[i]);
f[i] += i;
}
for(int i = n-1; i >= 0; i--){
r = f[i];
if(bl[r] != bl[i] || r >= n) to[i] = r, k[i] = 1;
else{
to[i] = to[r];
k[i] = k[r] + 1;
}
}
}
int ask(int x){
int he = 0;
while(x < n){
he += k[x]; x = to[x];
}
return he;
}
void change(int x, int y){
int j = bl[x], r;
f[x] = y; r = y;
if (bl[r] == bl[x]) to[x] = to[r], k[x] = k[r] + 1;
else to[x] = y, k[x] = 1;
for(int i = x-1; i >= 0; i--){
if(bl[i] != j) break;
r = f[i];
if(bl[r] == bl[i] && r < n) to[i] = to[r], k[i] = k[r] + 1;
else to[i] = r, k[i] = 1;
}
}
int main(){
init();
int j, aa, bb, cc;
scanf("%d", &m);
while(m--){
scanf("%d", &aa);
if(aa == 1){
scanf("%d", &bb);
printf("%d\n", ask(bb));
}
else{
scanf("%d%d", &bb, &cc);
cc += bb; change(bb, cc);
}
}
return 0;
}
/*
4
1 2 1 1
3
1 1
2 1 1
1 1
*/
/*
2
3
*/