CF1384B Koa and the Beach
CF1384B Koa and the Beach
https://codeforces.com/problemset/problem/1384/B1
题目大意
有点长,可以在luogu找到中文题面CF1384B1 Koa and the Beach (Easy Version) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
解题思路
一开始的思路是整一个线段树,从1-n循环遍历进行dp。转移思路就是,对于每一个位置找出可行的区间时间,然后查询和上一个位置的区间是否相邻。这两个操作可以用线段树来做。然而写完线段树才发现这个思路并不严谨,继续一思考才发现根本不用线段树。
这道题可以直接贪心地进行考虑,对于开始位置,我们要想让当前时刻地海浪尽可能高,这样后面地海浪会先降低再升高,用通俗地话来讲,就是留够足够地“余裕”。所以开始浪高我们能直接算出,为min(k, l - d[1]),往后走的过程中,我们使海浪继续随走动时间变化。这时候有两种特殊情况需要考虑。
① 如果这一步继续走,下一步会被淹没。
这种情况下,我们需要继续等待海浪降低,直到可以向前走,计算出值直接赋值。
如果当前的海浪正在上升,或者计算发现无论怎么等都无法满足,则输出-1
②如果海浪就算高到k也不会淹没。
那就一致等待直到海浪高为k,在程序上写作讲海浪位置赋值k。
原理和第一步的思路一样,为后面的路程留够足够地“余裕”。这样贪心就一定是最优的。
于是这道题就简单地做完啦!
因为时间复杂度是\(O(n)\),所以这个思路两个版本都可以通过!
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e2;
int n;
int k, l;
int d[maxn + 10];
void solve()
{
cin >> n >> k >> l;
for (int i = 1; i <= n; i++)
cin >> d[i];
if (d[1] > l) {
cout << "No\n";
return;
}
int pos = min(k, l - d[1]);
int f = 1;
for (int i = 2; i <= n; i++) {
if (f)
pos--;
else
pos++;
if (pos == -1 && f == 1) {
f = 0;
pos = 1;
}
if (pos + d[i] > l) {
if (f && l >= d[i]) {
pos = l - d[i];
}
else {
cout << "No\n";
return;
}
}
if (d[i] + k <= l) {
pos = k;
f = 1;
}
}
cout << "Yes\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}

浙公网安备 33010602011771号