bzoj2093 [Poi2010]Frog 倍增

本文介绍了一个跳跃算法的问题背景及解决方案,通过倍增技巧优化了搜索过程,实现高效确定从任一位置出发跳跃特定次数后的落点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description


一个条河无限宽,上面有n块石头,石头离左边的河岸(无限宽,右边河岸不晓得在哪)距离严格递增,现在Zxl想锻炼自己的跳跃能力(谁叫他在班里外号是鸟怪。。畸形),他在某一块石头上,想跳到离他这块石头第k远的石头上去,假如离他第k远的石头不是唯一的,他就选离岸最近的那一个(不然回不去了),他想你让他知道,从每块石头开始跳了m次后,自己在哪。

n, k <= 1,000,000
m <= 10^18
保证输入的n个正整数严格递增,并且不超过10^18。

Solution


这里的第k远实际上是第k近
搞懂了这个就好办了。用两个指针l和r扫,第一个点的第k近点显然是k+1,然后l和r向右移动的时候分两类讨论一下即可
m这么大可以考虑倍增,显然空间不够开那么滚掉一维就ok

Code


#include <stdio.h>
#include <string.h>
#include <math.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

typedef long long LL;
const int N=2000005;

int next[N],f[N],g[N],ans[N];

LL a[N],m;

int main(void) {
    int n,k; scanf("%d%d%lld",&n,&k,&m);
    rep(i,1,n) scanf("%lld",&a[i]);
    int l=1,r=k+1; next[1]=f[1]=k+1;
    rep(i,2,n) {
        while (r<n&&a[r+1]-a[i]<a[i]-a[l]) r++,l++;
        if (a[r]-a[i]<=a[i]-a[l]) next[i]=f[i]=l;
        else next[i]=f[i]=r;
    }
    rep(i,1,n) ans[i]=i;
    rep(j,0,(int)(log2(m)+1)) {
        if (((1<<j)&m)) {
            rep(i,1,n) ans[i]=f[ans[i]];
        }
        rep(i,1,n) g[i]=f[f[i]];
        rep(i,1,n) f[i]=g[i];
    }
    rep(i,1,n) printf("%d ",ans[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值