CF1384B Koa and the Beach
阿新 • • 發佈:2022-05-18
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; }