B2. Koa and the Beach (Hard Version)
原题:https://codeforces.ml/contest/1384/problem/B2
题意:给你n,k,l,表示koa距离目标的距离、涨潮的周期和koa的高度。koa一秒只能游泳一个距离。接着n个输入涨潮之前的海水高度。涨潮的规律是k秒上涨k秒下跌。当海水超过l时,koa就会被淹死。
分析:这题最重要的是建立分析思路。
首先我们将koa的状态分成三种:必活、必死和量子态。
必活:表示l>m+k这样无论如何涨潮都不会死。
必死:表示l<m这样无论如何都会死
贪心策略:每次必活点时都等待到海水最高时。
原因:如果等待k还没有必活点,那么任意一个上升点都一定会出现潮最高时,此时又不是必活点,koa就会死。
而当每次从海水最高点出发的时候,即使遇到了一些不太好的点,也能等待一会(如果是上升点他必死)。
最特殊的情况:落潮时要求:
tmp+water(last)<=l
因此water(last)<=l-tmp
这样就结束了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k,l;
ll water(ll x)
{
x%=(2*k);
if (x<k)
return x%k;
else
return k-(x%k);
}
ll judge(ll x)
{
x%=(2*k);
if (x<=k) return 0;
else return 1;
}
void rlmn()
{
scanf("%lld%lld%lld",&n,&k,&l);
ll last=k+1;
ll tmp;
ll ans=1;
while (n--)
{
scanf("%lld",&tmp);
if (tmp>l)//必死状态
{
ans=0;
}
else if (tmp+k<=l)//必活状态
{
last=k+1;
}
else
{
if (judge(last)==0)//说明现在在涨潮
{
if (tmp+water(last)>l)//现在活不下去,等更活不下去
{
ans=0;
}
else//否则会继续涨潮
{
last++;
}
}
else
{
if (tmp+water(last)<=l)
{
last++;
}
else
{
last=2*k-(l-tmp)+1;
}
}
}
}
if (ans==1) printf("Yes\n");
else printf("No\n");
}
int main()
{
int T;
scanf("%d",&T);
while(T--)rlmn();
return 0;
}