#659 (Div. 2) B. Koa and the Beach (Easy Version DP&&Hard Version 贪心)

题目描述

The only difference between easy and hard versions is on constraints. In this version constraints are higher. You can make hacks only if all versions of the problem are solved.
Koa the Koala is at the beach!
The beach consists (from left to right) of a shore, n+1 meters of sea and an island at n+1 meters from the shore.
She measured the depth of the sea at 1,2,…,n meters from the shore and saved them in array d. di denotes the depth of the sea at i meters from the shore for 1≤i≤n.
Like any beach this one has tide, the intensity of the tide is measured by parameter k and affects all depths from the beginning at time t=0 in the following way:
For a total of k seconds, each second, tide increases all depths by 1.
Then, for a total of k seconds, each second, tide decreases all depths by 1.
This process repeats again and again (ie. depths increase for k seconds then decrease for k seconds and so on …).
Formally, let’s define 0-indexed array p=[0,1,2,…,k−2,k−1,k,k−1,k−2,…,2,1] of length 2k. At time t (0≤t) depth at i meters from the shore equals di+p[tmod2k] (tmod2k denotes the remainder of the division of t by 2k). Note that the changes occur instantaneously after each second, see the notes for better understanding.
At time t=0 Koa is standing at the shore and wants to get to the island. Suppose that at some time t (0≤t) she is at x (0≤x≤n) meters from the shore:
In one second Koa can swim 1 meter further from the shore (x changes to x+1) or not swim at all (x stays the same), in both cases t changes to t+1.
As Koa is a bad swimmer, the depth of the sea at the point where she is can’t exceed l at integer points of time (or she will drown). More formally, if Koa is at x (1≤x≤n) meters from the shore at the moment t (for some integer t≥0), the depth of the sea at this point — dx+p[tmod2k] — can’t exceed l. In other words, dx+p[tmod2k]≤l must hold always.
Once Koa reaches the island at n+1 meters from the shore, she stops and can rest.
Note that while Koa swims tide doesn’t have effect on her (ie. she can’t drown while swimming). Note that Koa can choose to stay on the shore for as long as she needs and neither the shore or the island are affected by the tide (they are solid ground and she won’t drown there).
Koa wants to know whether she can go from the shore to the island. Help her!

Input

The first line of the input contains one integer t (1≤t≤104) — the number of test cases. Description of the test cases follows.
The first line of each test case contains three integers n, k and l (1≤n≤3⋅105;1≤k≤109;1≤l≤109) — the number of meters of sea Koa measured and parameters k and l.
The second line of each test case contains n integers d1,d2,…,dn (0≤di≤109) — the depths of each meter of sea Koa measured.
It is guaranteed that the sum of n over all test cases does not exceed 3⋅105.

Output

For each test case:
Print Yes if Koa can get from the shore to the island, and No otherwise.
You may print each letter in any case (upper or lower).

Example

input
7
2 1 1
1 0
5 2 3
1 2 3 2 2
4 3 4
0 2 4 3
2 3 5
3 0
7 2 3
3 0 2 1 3 0 1
7 1 4
4 4 3 0 2 4 2
5 2 3
1 2 3 2 2
output
Yes
No
Yes
Yes
Yes
No
No

Note

In the following s denotes the shore, i denotes the island, x denotes distance from Koa to the shore, the underline denotes the position of Koa, and values in the array below denote current depths, affected by tide, at 1,2,…,n meters from the shore.
In test case 1 we have n=2,k=1,l=1,p=[0,1].
Koa wants to go from shore (at x=0) to the island (at x=3). Let’s describe a possible solution:
Initially at t=0 the beach looks like this: [s–,1,0,i].
At t=0 if Koa would decide to swim to x=1, beach would look like: [s,2–,1,i] at t=1, since 2>1 she would drown. So Koa waits 1 second instead and beach looks like [s–,2,1,i] at t=1.
At t=1 Koa swims to x=1, beach looks like [s,1–,0,i] at t=2. Koa doesn’t drown because 1≤1.
At t=2 Koa swims to x=2, beach looks like [s,2,1–,i] at t=3. Koa doesn’t drown because 1≤1.
At t=3 Koa swims to x=3, beach looks like [s,1,0,i–] at t=4.
At t=4 Koa is at x=3 and she made it!
We can show that in test case 2 Koa can’t get to the island.

题目大意

有 n 片海域,每片海域有一个初始深度,每 2 * k秒,前 k秒 每秒深度 +1 ,后 k 秒每秒深度 -1 .有一个人想从海岸一边游到另一边 ,每秒它可以移动到下一片海域或者停留在当前海域,如果当前海域深度大于 l 他会被淹死,问他可不可以游到对岸。

Easy Version

题目分析

这道题可以通过dp来做。
状态表示:f[i][j] //当这个人到达第i片海域的时间为j秒这个状态是否合法
状态计算:f[i][j]可以由两个状态转移得到
f[i][j-1] //上一秒在第i片海域选择不移动
f[i-1][j-1] //上一秒在第i-1片海域选择向右移动
只要两者有一个状态是合法的,那么f[i][j]就是可到达的。
然后我们还要证明f[i][j]状态本身是否合法,即在第j秒时海域i的深度是否大于l。
最后我们只需要找找f[n][j]的状态中是否有合法的即可,如果f[n][j]状态中有合法的,那么最终的结果就是Yes.

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <iomanip>
#define LL long long
#define PII pair<int,int>
using namespace std;
const int N=1e2+5,M=2e4+5;
int a[N],p[2*N];
int f[N][M];
void init(int k)
{
	for(int i=0;i<=k;i++) p[i]=i;		//预处理出涨潮的情况
	for(int i=1;i<k;i++) p[k+i]=k-i;
	
	for(int i=0;i<2*k;i++) f[0][i]=1;	//设置起点,进去的时间区间在[0,2k]内即可
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(f,0,sizeof f);
		int n,k,l;
		cin>>n>>k>>l;
		for(int i=1;i<=n;i++)
			cin>>a[i];
		
		init(k);
		for(int i=1;i<=n;i++)			//枚举海域
		for(int j=0;j<2*k*n;j++)		//枚举时间
		{
			f[i][j]=max(f[i][j-1],f[i-1][j-1]);		//计算状态f[i][j]是否可到达
			if(l<p[j%(2*k)]+a[i]) f[i][j]=0;		//计算f[i][j]本身是否合法
		}
		bool ok=false;
		for(int i=0;i<2*k*n;i++)
			if(f[n][i]) ok=true;
		
		if(ok) puts("Yes");
		else puts("No");
	}
	return 0;
}

Hard Version

题目分析

首先我们要求出每个海域a[i]在哪个时间段[li,ri]内能够通过(即:a[i]+p[t]<=l,li<=t<=ri)。
但是涨潮的周期为Λ型(0-k-0),这样的话[li,ri]区间是分开的,不好计算。因此我们可以先重新定义一下涨潮的周期,把它变为V型(k-0-k,因为不用考虑用数,所以往后推k秒其实也无所谓)。这样[li,ri]即为一个连续的区间了,方便计算。
li即为开始时的水深减去l(a[i]+k-l),ri肯定在li对称的另一边,因此ri=2*k-li。
然后我们只需要选择li时刻进入即可。在1-n的海中,如果某块海域a[i]+k<=l即为安全海域,那么我们在这块海域呆多久都没事,这时我们就可以调整时间,等到下一块海域到了li时刻在进入继续向前即可。如果某块海域不是安全海域,那么就不要停留,因为在非安全海域中随着时间推移(涨潮)我就可能会被淹死。
如果游到了某块海域a[i-1]时的时间为t,t+1>ri的话,我们就会在下一块海域被淹死,因此不能游过去(No)。否则顺利进入下一块海域,t+1。最后能到达n位置则为Yes。

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <iomanip>
#define LL long long
#define PII pair<int,int>
using namespace std;
const int N=3e5+5;
int a[N]; 
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,k,l;
		scanf("%d %d %d",&n,&k,&l);
		int maxv=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			maxv=max(maxv,a[i]);
		}
		if(maxv>l) 
		{
			puts("No"); continue;
		}
		else if(maxv+k<=l)
		{
			puts("Yes"); continue;
		}
		int t=-1;
		bool st=0;
		for(int i=1;i<=n;i++)
		{
			int li=max(0,k+a[i]-l),ri=2*k-li;	//计算li和ri,li结果要保证大于0
			if(a[i]+k<=l)		//是否为安全海域
			{
				st=true;
				continue;
			}
			if(st)				//如果上一位置为安全海域,那么这里可以选择li时刻在前进
			{
				t=li;
				st=false;
				continue;
			}
			if(ri>=t+1) t=max(li,t+1);	//没超出ri则可以进行前进
			else {t=-1; break;}			//否则失败
		}
		if(t<0) puts("No");
		else puts("Yes"); 
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值