[题解]弹飞绵羊

分块骗分

记跳出本块步数和到达的位置,倒序递推

修改暴力修改块内

把复杂度从查询摊到修改上

#include<bits/stdc++.h>
using namespace std;
const int maxn=200009;
const int maxm=509;
int n,m,q,t;
int L[maxn],R[maxn],k[maxn],bl[maxn];
int step[maxn],to[maxn];
inline void change(int x,int y){
    k[x]=y;
    for(int i=L[bl[x]+1]-1;i>=L[bl[x]];i--)
    if(i+k[i]>=L[bl[i]+1])step[i]=1,to[i]=i+k[i];
    else step[i]=step[i+k[i]]+1,to[i]=to[i+k[i]];
}
inline int query(int x){
    int ans=0;
    while(x<=n)ans+=step[x],x=to[x];
    return ans;
}
int main(){
    scanf("%d",&n);
    t=sqrt(n);
    for(int i=1;i<=n;i++){
        scanf("%d",&k[i]);
        bl[i]=(i-1)/t+1;
        if(bl[i]!=bl[i-1])L[bl[i]]=i;
    }
    L[bl[n]+1]=n+1;
    for(int i=n;i>=1;i--){
        if(i+k[i]>=L[bl[i]+1]){
            step[i]=1;to[i]=i+k[i];
        }
        else{
            step[i]=step[i+k[i]]+1;
            to[i]=to[i+k[i]];
        }
    }
    scanf("%d",&m);
    for(int i=1,op,x,y;i<=m;i++){
        scanf("%d%d",&op,&x);x++;
        if(op==1){
            printf("%d\n",query(x));
        }
        else{
            scanf("%d",&y);
            change(x,y);
        }
    }
}

 

posted @ 2019-10-19 08:31  羊肉汤泡煎饼  阅读(117)  评论(0编辑  收藏  举报