題解 P3551 【[POI2013]USU-Take-out】
阿新 • • 發佈:2020-07-21
Solution USU-Take-out
題目大意:給定\(n\)塊磚,黑磚是白磚的\(k\)倍,每次可以拿出\(k + 1\)塊磚,要求其中只有\(1\)塊白磚,且相鄰兩塊磚之間的所有磚都還沒有被拿出來過,求一種可行方案
貪心、棧
分析:首先不考慮相鄰磚之間磚沒有被拿出來的限制,我們可以想到一種貪心的做法
維護一個棧,如果棧頂的\(k + 1\)塊磚裡只有\(1\)塊白磚,彈出\(k + 1\)塊磚,將它們的位置作為一次操作
容易發現,第一次彈的\(k + 1\)塊磚一定是連續的,後面彈的磚雖然在棧裡面連續,但在原序列中兩兩之間的磚都被拿掉了
所以我們只要把彈棧得到操作的順序倒過來,就可以保證操作的合法性了
#include <iostream> #include <sstream> #include <algorithm> using namespace std; const int maxn = 1e6 + 100; char str[maxn]; string ans[maxn]; int n,k,cnt,top,tot,stk[maxn]; int main(){ ios::sync_with_stdio(false); cin >> n >> k; cin >> (str + 1); for(int i = 1;i <= n;i++){ stk[++top] = i; cnt += (str[i] == 'c'); if(top > k + 1)cnt -= (str[stk[top - k - 1]] == 'c'); if(cnt == 1 && top >= k + 1){ ostringstream tmp; for(int i = top - k;i <= top;i++) tmp << stk[i] << " "; ans[++tot] = tmp.str(); cnt = 0; for(int i = top - k - 1;i >= max(top - k - 1 - k,1);i--)cnt += (str[stk[i]] == 'c'); top -= k + 1; } } for(int i = tot;i >= 1;i--) cout << ans[i] << '\n'; return 0; }