BZOJ2002 HNOI2010 Bounce 弹飞绵羊 题解&代码

26 篇文章 0 订阅
1 篇文章 0 订阅

这几天一直在bzoj水不能见人的水题…有时间补补题解吧【说得好像这题不水一样
很简单的分块!
第一次写到这么简单的分块!
整个人都舒爽了!
虽然还是WA了两次…妈的我只是写完一激动忘了输出后加回车…

将整个长区间分成近似于sqrt(n)块【分块方法随意,满足可逆性即可
对于每一块,处理出块内每个点弹出这一块所需步数
然后每次查询最多累计sqrt(n)次(块数次)
每次修改最多修改sqrt(n)次(块大小次)
完美【呸

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 200005;
int n,m,len,c,x,y,k[maxn],block[maxn],next[maxn],step[maxn];
void f(int p,int i)
{
    if(p>=n)step[i] = 1, next[i]=-1;
        else if(block[p]!=block[i]) step[i]=1,next[i]=p;
                else step[i] = step[p]+1, next[i]=next[p];

}
void cal(void)
{
    for(int i = n-1; i >= 0; i--)
        f(i+k[i],i);
}
int query(int x,int ret)
{
    ret+=step[x];
    if(next[x]==-1)return ret;
    return query(next[x],ret);
}
void change(int x,int y)
{
    if(k[x]==y)return;
    k[x]=y;
    int temp =(block[x]-1)*len;
    for(int i = x; i >= temp; i--)
        f(i+k[i],i);
}
int main (void)
{
    scanf("%d",&n);
    len = sqrt(n);
    for(int i = 0; i < n; i++)
    {
        scanf("%d",&k[i]);
        block[i]=i/len+1;
    }
    cal();
    scanf("%d",&m);
    for(int i = 0; i < m; i++)
    {
        scanf("%d%d",&c,&x);
        if(c==1)printf("%d\n",query(x,0));
        else
        {
            scanf("%d",&y);
            change(x,y);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值