2093: [Poi2010]Frog

2093: [Poi2010]Frog

Time Limit: 10 Sec   Memory Limit: 259 MB
Submit: 507   Solved: 161
[ Submit][ Status][ Discuss]

Description

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

Input

第一行有3个由空格隔开的整数n, k (n, k <= 1,000,000), m (m <= 10^18)。
第二行有n个正整数,第i个数表示第i块石头离左岸的距离,保证输入的n个正整数严格递增,并且不超过10^18。

Output

一行n个由空格隔开的整数,第i个表示Zxl从第i块石头开始跳,跳m次后会在哪个石头上。

Sample Input

5 2 4
1 2 4 7 10

Sample Output

1 1 3 1 1

HINT

Source

[ Submit][ Status][ Discuss]

先要求出每个点的第K远点分别是哪个
这具有显然的决策单调性,,所以Sliding Windows就行了
然后就剩下一个环套树了,直接跑倍增就行。。
注意数组开太大的话调用的常数很大,所以用滚动数组
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 1E6 + 5;
const int T = 60;
typedef long long LL;

int n,tot,k,p,q = 1,nex[maxn][2],Ans[maxn];
LL m,A[maxn];

LL dis(const int &x,const int &y) {return abs(A[x] - A[y]);}

LL getLL()
{
	char ch = getchar(); LL ret = 0;
	while (ch < '0' || '9' < ch) ch = getchar();
	while ('0' <= ch && ch <= '9')
		ret = ret*10LL + 1LL*(ch - '0'),ch = getchar();
	return ret;
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	n = getLL(); k = getLL(); m = getLL();
	for (int i = 1; i <= n; i++) A[i] = getLL();
	int L = 1,R = k + 1; nex[1][0] = R;
	for (int i = 2; i <= n; i++)
	{
		while (R < n && dis(R + 1,i) < dis(L,i)) ++L,++R;
		nex[i][0] = dis(L,i) >= dis(R,i) ? L : R;
	}
	for (int i = 1; i <= n; i++) Ans[i] = i;
	while (m)
	{
		if (m&1)
		{
			for (int i = 1; i <= n; i++) Ans[i] = nex[Ans[i]][p];
		}
		for (int i = 1; i <= n; i++) nex[i][q] = nex[nex[i][p]][p];
		swap(p,q); m >>= 1LL;
	}
	for (int i = 1; i < n; i++) printf("%d ",Ans[i]); cout << Ans[n];
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值