给一个数组,有两种操作,一种是将a位数改成b,一种是判断从a点跳几次能跳出数组,每次跳从a到x【a】+a
题解:用两个数组记录,每次点跳出下一个块 的次数,和跳到下一个块 的位置,用块来不断更新,查找的时候直接暴力跳每一个块,到最后一个块就挨个跳,
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=200000+10,maxn=60000+10,inf=0x3f3f3f3f; int n,m,block,num; int l[N],r[N],belong[N]; int Next[N],cnt[N],a[N]; void build() { block=(int)sqrt(n+0.5); 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--) { int p=i,f=0; cnt[i]=1; while(belong[p+a[p]]==belong[p]) { if(Next[p+a[p]]) { cnt[i]=cnt[p+a[p]]+1; Next[i]=Next[p+a[p]]; f=1; break; } cnt[i]++; p=p+a[p]; if(p+a[p]>n)break; } if(!f)Next[i]=p+a[p]; } } void update(int x,int y) { a[x]=y; for(int i=r[belong[x]];i>=l[belong[x]];i--) { int p=i,f=0; cnt[i]=1; while(belong[p+a[p]]==belong[p]) { if(Next[p+a[p]]) { cnt[i]=cnt[p+a[p]]+1; Next[i]=Next[p+a[p]]; f=1; break; } cnt[i]++; p=p+a[p]; if(p+a[p]>n)break; } if(!f)Next[i]=p+a[p]; } } void query(int x) { int ans=1; while(x<=n) { if(Next[x]>n) { while(x+a[x]<=n)ans++,x=x+a[x]; printf("%d ",x); break; } else { ans+=cnt[x]; x=Next[x]; } } printf("%d ",ans); } void debug() { for(int i=1;i<=n;i++) printf("%d %d ",Next[i],cnt[i]); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); build(); // debug(); while(m--) { int x,y; scanf("%d",&x); if(x==0) { scanf("%d%d",&x,&y); update(x,y); } else { scanf("%d",&x); query(x); } // debug(); } return 0; } /******************** ********************/
复杂度O(n*sqrt(n)