1. 程式人生 > 實用技巧 >(CF1384B2)Koa and the Beach (Hard Version)

(CF1384B2)Koa and the Beach (Hard Version)

做法:貪心

對於每一個永遠安全的點,我們都可以在他上面等待到任意時刻,那麼當tide到達k時出發,向下一個安全點前進必然是最優的。

證明:
假設一種處於兩個安全點中間的狀態,這個時候tide已經在上升了,但這個點的深度又超過了限制,那麼能否嘗試將出發提前,即在上升的時候就出發呢?
由於安全點之間的點的深度+k必然大於限制,那麼仍然需要等待,故tide出發時必然最優(改變狀態設計好像也可以不從k出發,不過那樣就沒有一個明確的界線了)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Ls t[p<<1]
#define Rs t[p<<1|1]
#define fastio ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
const int maxn = 1e6 + 10;
const ll inf = 1e17;

ll mod = 998244353;

int main()
{
    //freopen("C:\\1.in", "r", stdin);
    fastio;
    int t;
    cin >> t;
    while (t--)
    {
        ll n, k, l;
        cin >> n >> k >> l;
        vector<ll>d(n + 1);
        vector<int>saf;//路程中完全安全的點
        saf.push_back(0);
        for (int i = 1; i <= n; i++)
        {
            cin >> d[i];
            if (d[i] + k <= l)saf.push_back(i);
        }
        saf.push_back(n + 1);
        bool flag = 1;
        for (int i = 1; i < saf.size(); i++)
        {
            bool down = 1;
            ll tide = k;//從潮汐從最高往下降時開始貪心
            for (int j = saf[i-1] + 1; j < saf[i]; j++)
            {
                down == 1 ? --tide : ++tide;//當前tide狀態
                if (d[j] + tide > l)//waiting。。。
                {
                    if (!down) { flag = 0; break; }//如果已經在上升了
                    tide -= d[j] + tide - l;
                }
                if (tide < 0)//沒辦法下降到期待高度
                {
                    flag = 0;
                    break;
                }
                if (tide == 0)
                    down = 0;
            }
        }
        if (flag)cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    return 0;

}