码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P3509 [POI2010]ZAB-Frog

时间:2020-12-05 11:00:09      阅读:8      评论:0      收藏:0      [点我收藏+]

标签:while   c++   else   ref   mes   lan   r++   main   ++   

https://www.luogu.com.cn/problem/P3509

题面

数轴上有n个点,有一个青蛙在这些点上跳;
规则是每次向距当前点第k小的点跳,如果有相同距离则向下标较小的跳;
求从每个点出发跳了m次后在哪里;
\(n\leq 10^5 ,m\leq 10^{18}\)

分析

显然倍增,考虑如何求出距当前点距离\(K\)小点
显然距离前K小点的点集在数轴上是连续的且单调增
所以用单调队列维护

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int N=1e5+5;
int n,k; 
ll m,a[N];
int f[N][60];

int main() {
	scanf("%d%d%lld",&n,&k,&m);
	for(int i=1;i<=n;i++) {
		scanf("%lld",&a[i]);
	}
	int l=1,r=k+1;
	f[1][0]=r;
	for(int i=2;i<=n;i++) {
		while(r<n&&a[i]-a[l]>a[r+1]-a[i]) r++,l++;
		if(a[i]-a[l]>=a[r]-a[i]) f[i][0]=l;
			else f[i][0]=r;
	}
	for(int j=1;j<60;j++) {
		for(int i=1;i<=n;i++) {
			f[i][j]=f[f[i][j-1]][j-1];
		}
	}
	for(int i=1;i<=n;i++) {
		int now=i; ll res=m;
		for(int j=59;j>=0;j--) {
			if(res>=(1LL<<j)) {
				res-=(1LL<<j);
				now=f[now][j];
			}
		}
		printf("%d ",now);
	}
	return 0;
}

Luogu P3509 [POI2010]ZAB-Frog

标签:while   c++   else   ref   mes   lan   r++   main   ++   

原文地址:https://www.cnblogs.com/wsfwsf/p/14068028.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!