题意:
分析:
分块就是暴力,但用了一个块来有优化时间,要想用分块,就要想办法借助块来优化。一开始做这道题目,完全想不出来要维护什么东西,分块怎么用。看了别人的思路后,明白了要维护每个点跳出其所在块的跳的次数和跳到的点。写了之后,一交就 (WA) 了。后来发现是修改点的时候,没有把其所在块中该点前面的点也修改。因为,修改该点时,它们各自维护的东西可能会受到影响。然后,又交,(T) 了。发现,是在修改各个点时,完全可以用递推的方式来改,而我每次都重新开始。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
struct node
{
int step,pos;
}point[N];
int k[N],belong[N],L[N],R[N];
int num,block,n;
void read(int &x)
{
x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
x*=f;
}
void build()
{
block=sqrt(n);
num=n/block;
if(n%block)
num++;
for(int i=1;i<=num;i++)
{
L[i]=(i-1)*block+1;
R[i]=i*block;
}
R[num]=n;
for(int i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
for(int i=n;i>=1;i--)
{
if(i+k[i]>R[belong[i]])
{
point[i].step=1;
point[i].pos=i+k[i];
}
else
{
point[i].step=point[i+k[i]].step+1;
point[i].pos=point[i+k[i]].pos;
}
}
}
void update(int p)
{
for(int i=p;i>=L[belong[p]];i--)
{
if(i+k[i]>R[belong[p]])
{
point[i].step=1;
point[i].pos=i+k[i];
}
else
{
point[i].step=point[i+k[i]].step+1;
point[i].pos=point[i+k[i]].pos;
}
}
}
int query(int p)
{
int ans=0;
while(p<=n)
{
ans+=point[p].step;
p=point[p].pos;
}
return ans;
}
int main()
{
int m,op,a,b;
read(n);
for(int i=1;i<=n;i++)
read(k[i]);
build();
read(m);
while(m--)
{
read(op),read(a);
if(op==1)
printf("%d
",query(a+1));
else if(op==2)
{
read(k[a+1]);
update(a+1);
}
}
return 0;
}