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;
}
posted @ 2022-05-18 21:05  icey_z  阅读(45)  评论(0)    收藏  举报