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;
}