BZOJ 1345[BOI]序列问题 - 贪心 + 单调栈
题解
真的没有想到是单调栈啊。 回想起被单调栈支配的恐惧
最优情况一定是小的数去合并 尽量多的数,所以可以维护一个递减的单调栈。
如果加入的数比栈首小, 就直接推入栈。
如果加入的数大于等于栈首, 必须要合并栈首,因为栈首两边都是大的数, 要选择小的那个进行合并, 需要进行$st[top - 1] 与 x$判断大小。
最后留下来的递减数列逐个合并就可以了
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #define rd read() 5 using namespace std; 6 7 const int N = 1e6 + 1e5; 8 9 int st[N], tp, n; 10 long long ans; 11 12 int read() { 13 int X = 0, p = 1; char c = getchar(); 14 for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1; 15 for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 16 return X * p; 17 } 18 19 int main() 20 { 21 n = rd; 22 for(int i = 1; i <= n; ++i) { 23 int x = rd; 24 while(tp && st[tp] <= x) { 25 if(tp > 1 && st[tp - 1] < x) ans += st[tp - 1]; 26 else ans += x; 27 tp--; 28 } 29 st[++tp] = x; 30 } 31 while(tp > 1) { 32 ans += st[--tp]; 33 } 34 printf("%lld\n", ans); 35 }