BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 [分块]

题意:

修改一个数

从i开始每次到$a_i$,超过n需要几次


分块跑的比LCT都快......

每个块维护块内每个点几步跳出块并跳到哪个位置

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=2e5+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int n,a[N],Q,op,x;
struct Block{
    int block,m,pos[N],f[N],g[N];
    void ini(){
        block=sqrt(n); m=(n-1)/block+1;
        for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
        //for(int i=1;i<=m;i++) l[i]=(i-1)*block+1,r[i]=i*block;
        //r[m]=n;

        for(int i=n;i>=1;i--){
            if(pos[i]==pos[a[i]]) f[i]=f[a[i]]+1,g[i]=g[a[i]];
            else f[i]=1,g[i]=a[i];
        }
    }
    int que(int x){
        int re=0;
        for(int i=x;i<=n;i=g[i]) re+=f[i];
        return re;
    }
    void cha(int x,int v){
        a[x]=x+v; int l=(pos[x]-1)*block+1;
        for(int i=x;i>=l;i--){
            if(pos[i]==pos[a[i]]) f[i]=f[a[i]]+1,g[i]=g[a[i]];
            else f[i]=1,g[i]=a[i];
        }
    }
}B;
int main(){
    freopen("in","r",stdin);
    n=read();
    for(int i=1;i<=n;i++) a[i]=read()+i;
    B.ini();
    Q=read();
    while(Q--){
        op=read();x=read()+1;
        if(op==1) printf("%d\n",B.que(x));
        else B.cha(x,read());
    }
}

 

posted @ 2017-03-15 08:39  Candy?  阅读(92)  评论(0编辑  收藏