首页 > 其他 > 详细

【Luogu】P3203弹飞绵羊(分块)

时间:2018-01-20 22:31:27      阅读:241      评论:0      收藏:0      [点我收藏+]

  题目链接

  正解是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;
}

 

【Luogu】P3203弹飞绵羊(分块)

原文:https://www.cnblogs.com/cellular-automaton/p/8321896.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!