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

题目:中文题,略

思路:看了黄学长的博客,之前一直听大腿吹,今天写了弹飞绵羊,有趣,其实这个题是维护了两个东西,一个是我第i个位置的下一个位置在哪,如果在同一块我就直接连接到下一个下一块的位置,我只在一个块上走一次,这样我有sqrtn块,所以查询和修改都是sqrt(n)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
inline LL read()
{
    LL x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int maxn=2e5+7;
int n,m,block,cnt;
int to[maxn],st[maxn],K[maxn],belong[maxn];
int l[1005],r[1005];
int main()
{
    n=read();block=sqrt(n);
    for(int i=1;i<=n;i++){
        K[i]=read();
    }
    int cnt=n/block;
    if(n%block)cnt++;
    for(int i=1;i<=n;i++){
        belong[i]=(i-1)/block+1;
    }
    for(int i=1;i<=cnt;i++){
        l[i]=(i-1)*block+1;
        r[i]=(i)*block;
    }
    r[cnt]=n;
    for(int i=n;i>0;i--){
        if(i+K[i]>n)st[i]=1,to[i]=0;
        else if(belong[i]==belong[i+K[i]])
            st[i]=st[i+K[i]]+1,to[i]=to[i+K[i]];
        else st[i]=1,to[i]=i+K[i];
    }
    m=read();
    while(m--){
        int op=read();
        if(op==1){
            int pos=read();
            pos++;
            int ans=0;
            while(true){
                ans+=st[pos];
                if(!to[pos])break;
                pos=to[pos];
            }
            printf("%d\n",ans);
        }
        else{
            int pos=read(),val=read();
            pos++;K[pos]=val;
            for(int i=pos;i>=l[belong[pos]];i--){
                if(belong[i]==belong[i+K[i]])
                    st[i]=st[i+K[i]]+1,to[i]=to[i+K[i]];
                else st[i]=1,to[i]=i+K[i];
            }
        }
    }
    return 0;
}
/*
4
1 2 1 1
3
1 1
2 1 1
1 1
*/

 

posted @ 2018-08-06 21:33  啦啦啦天啦噜  阅读(146)  评论(0编辑  收藏