题目:
洛谷 P3203
分析:分块。每个块记录这个位置到第一个离开这个块的位置,以及到这个块的距离。可以O(n)预处理,每次修改暴力修改这个块。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
const int maxn=200005;
using namespace std;
int test,n,i,block,num,j,c,xx,yy;
int a[maxn],next[maxn],dis[maxn],belong[maxn],l[2001],r[2001];
void build_block()
{
block=trunc(sqrt(n));
num=n/block+(n%block!=0);
for (i=1;i<=num;i++)
{
l[i]=(i-1)*block+1;
r[i]=i*block;
}
r[num]=n;
for (i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
}
int getsum(int x)
{
int ans=0;
i=x;
while (i<=n)
{
ans+=dis[i];
i=next[i];
}
return ans;
}
void dfs(int x,int c,int &ne,int &k)
{
if (belong[x]!=c)
{
ne=x;
k=0;
return;
}
if (next[x]!=0)
{
ne=next[x];
k=dis[x];
return;
}
dfs(min(x+a[x],maxn),c,ne,k);
next[x]=ne;
k++;
dis[x]=k;
}
void change(int x,int y)
{
a[x]=y;
int t=belong[x];
int i,j,k;
for (i=l[t];i<=r[t];i++)
{
next[i]=0;
}
for (i=l[t];i<=r[t];i++)
{
if (next[i]==0)
{
dfs(i,t,xx,yy);
}
}
}
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build_block();
for (i=1;i<=n;i++)
{
if (next[i]==0)
{
dfs(i,belong[i],xx,yy);
}
}
scanf("%d",&test);
while (test--)
{
int op,x,y;
scanf("%d",&op);
if (op==1)
{
scanf("%d",&x);
printf("%d\n",getsum(x+1));
}
else
{
scanf("%d%d",&x,&y);
change(x+1,y);
}
}
}