题目描述
某天,Lostmonkey 发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。
游戏一开始,Lostmonkey 在地上沿着一条直线摆上 n n n 个装置,每个装置设定初始弹力系数 k i k_i ki ,当绵羊达到第 i i i 个装置时,它会往后弹 k i k_i ki 步,达到第 i + k i i+k_i i+ki 个装置,若不存在第 i + k i i+k_i i+ki 个装置,则绵羊被弹飞。
绵羊想知道当它从第 i i i 个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey 可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
输入格式
第一行包含一个整数
n
n
n,表示地上有
n
n
n 个装置,装置的编号从
0
∼
n
−
1
0∼n−1
0∼n−1。
接下来一行有
n
n
n 个正整数,依次为那
n
n
n 个装置的初始弹力系数。
第三行有一个正整数
m
m
m,表示操作次数。接下来
m
m
m 行每行至少有两个数
i
,
j
i,j
i,j。
若
i
=
1
i=1
i=1,你要输出从
j
j
j 出发被弹几次后被弹飞
若
i
=
2
i=2
i=2,则还会再输入一个正整数
k
k
k,表示第
j
j
j 个弹力装置的系数被修改成
k
k
k。
输出格式
对于每个 i = 1 i=1 i=1 的操作,输出一行一个整数表示答案。
输入输出样例
输入 #1
4
1 2 1 1
3
1 1
2 1 1
1 1
输出 #1
2
3
///被三目运算符的优先级坑了一次_(:з」∠)_
#include<algorithm>
#include<iostream>
//#include<stdio.h>
#include<vector>
#include<string>
#include<cstring>
#include<math.h>
#include<iomanip>
using namespace std;
//#define int long long
const int manx=4e5+10;
const int manx2=1e7+10;
const int mod=1e9+7;
const double inf=1e9+7;
int n,m,slen;//slen每个块大小
int a[manx],times[manx],net[manx];//times需要几次跳出块//net出块位置
//有点记忆化的影子
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
slen=sqrt(n);//根据需要,一般大小设置为sqrt(n)
for(int i=n;i>=1;i--)//预处理 倒序
{
int temp=i/slen+((i%slen==0)?0:1);//i在第几个块
if(i+a[i]>slen*temp||i+a[i]>n)
times[i]=1,net[i]=i+a[i];
else//跳一次后还在当前块,倒序处理就可以就直接加上下一个位置的times
{
times[i]=1+times[i+a[i]];
net[i]=net[i+a[i]];
}
}
int i,j,k;
cin>>m;
while(m--)
{
cin>>i>>j;
j++;
if(i==1)
{
int ans=0;
while(j<=n)
{
ans+=times[j];
j=net[j];
}
cout<<ans<<endl;
}
else
{
cin>>k;
a[j]=k;
int temp=j/slen+((j%slen==0)?0:1);
for(int i=j;i>=(temp-1)*slen+1;i--)
{
if(i+a[i]>slen*temp||i+a[i]>n)
times[i]=1,net[i]=i+a[i];
else
{
times[i]=1+times[i+a[i]];
net[i]=net[i+a[i]];
}
}
}
}
return 0;
}