LuoguP3203弹飞绵羊(分块)

Posted cellular-automaton

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LuoguP3203弹飞绵羊(分块)相关的知识,希望对你有一定的参考价值。

  题目链接

  正解是LCT但我不会呀蛤蛤蛤蛤蛤

  (分块我也没想出来

  把区间分成根n个块,每个块内记录两个东西,就是该位置弹多少次能够弹出这个块,以及该位置弹到最后弹出去了之后能够弹到哪里。

  然后查询就一个块一个块的跳,修改就暴力重构这个块。

  

#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
#include<cstdlib>
#define maxn 200010
#define sqtn 450
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch==-)    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-0;
        ch=getchar();
    }
    return num*f;
}

int q[maxn];
int s[maxn];
int le[maxn],ri[maxn];

struct Block{
    int out[sqtn],nxt[sqtn];
}d[sqtn];

void update(int i){
    Block &o=d[i];
    for(int j=ri[i];j>=le[i];--j){
        int x=j-le[i]+1;
        o.nxt[x]=j+q[j];
        if(o.nxt[x]>ri[i])    o.out[x]=1;
        else{
            o.out[x]=o.out[o.nxt[x]-le[i]+1]+1;
            o.nxt[x]=o.nxt[o.nxt[x]-le[i]+1];
        }
    }
}

int main(){
    int n=read();int sqt=sqrt(n),blo=0;
    for(int i=1;i<=n;++i){
        q[i]=read();
        s[i]=(i-1)/sqt+1;
        if(s[i]>blo)    blo=s[i];
        ri[s[i]]=i;
    }
    for(int i=n;i>=1;--i)    le[s[i]]=i;
    for(int i=1;i<=blo;++i)    update(i);
    int m=read();
    for(int i=1;i<=m;++i){
        int opt=read(),x=read()+1;
        if(opt==1){
            int pos=x,ans=0;
            while(pos<=n){
                ans+=d[s[pos]].out[pos-le[s[pos]]+1];
                pos=d[s[pos]].nxt[pos-le[s[pos]]+1];
            }
            printf("%d\n",ans);
        }
        else{
            int y=read();
            q[x]=y;
            update(s[x]);
        }
    }
    return 0;
}

 

以上是关于LuoguP3203弹飞绵羊(分块)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002

p3203 弹飞绵羊

AC日记——[HNOI2010]BOUNCE 弹飞绵羊 洛谷 P3203

洛谷P3203 [HNOI2010]弹飞绵羊LCT

[HNOI2010]BOUNCE 弹飞绵羊

[BZOJ 2002][Luogu 3203][HNOI2010]Bounce 弹飞绵羊