题意:
有n个洞,每个洞有一个power值,表示进入这个洞的球能够被弹到i+power处,两种操作
1.将a洞的power改为b
2.询问从洞a开始放一个球,能被弹出的次数和最终位置
题解:
分块处理,每个块中处理每个点被弹出这个块的位置和次数。
调整了一下块的大小,优化了500ms+
#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 100005
struct node
{
int step;
int x;
} que[maxn];
int a[maxn];
int n,m;
int block,num,belong[maxn],l[maxn],r[maxn];
void init()
{
block=sqrt(2*n);
num=n/block;
if(n%block) num++;
for(int i=1; i<=n; i++)
{
belong[i]=(i-1)/block+1;
}
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<=num; i++)
{
for(int j=r[i]; j>=l[i]; j--)
{
if(j+a[j]>r[i])
{
que[j].x=j+a[j];
que[j].step=1;
}
else
{
que[j]=que[j+a[j]];
que[j].step++;
if(que[j].x>r[i]) que[j].x=j+a[j],que[j].step--;
}
}
}
}
void update(int x,int y)
{
a[x]=y;
int pos=belong[x];
for(int i=r[pos]; i>=l[pos]; i--)
{
if(i+a[i]>r[pos])
{
que[i].x=i+a[i];
que[i].step=1;
}
else
{
que[i]=que[i+a[i]];
que[i].step++;
if(que[i].x>r[pos]) que[i].x=i+a[i],que[i].step--;
}
}
}
void query(int x)
{
int pos=belong[x];
int ans1=0,ans2=x;
while(x<=n)
{
ans1+=que[x].step;
ans2=x;
if(x==que[x].x) break;
x=que[x].x;
}
printf("%d %d\n",ans2,ans1);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
init();
while(m--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x;
scanf("%d",&x);
query(x);
}
else
{
int x,y;
scanf("%d%d",&x,&y);
update(x,y);
}
}
return 0;
}