CSU-ACM 1838: Water Pump(单调栈+前缀后缀和)
来源:互联网 发布:淘宝上比较好的女装 编辑:程序博客网 时间:2024/05/29 17:56
特记
专为某人写的题解,记住哟,要思考思考
题意
给你
解题思路
思路一
如果当前我们选择i 处开通下水管,那么最终的状态就是,左边的水都会满,右边的水都会满,而i 处的水都会被放掉,那么遵循这个思路,我们先运用单调栈保存到当前位置距离i 最近并且比i 处的墙高或者最接近i 高度的墙的位置在哪里,如下图:
然后从左边求一遍以1 为起点以i 为终点,这之间水填满时的水量为dpl[i] ,同理从右边求一遍dpr[i] ,最终的答案就是=全部填满的水量−min{dpl[i]+dpr[i+1]} 思路二
以i 处为中心,往左边找最高的墙,往右边找最高的墙,然后直接计算空出来的空间是多少即是排出去的水量(当然这方法会出现超时,因为每一次都要找最高的会导致遍历几乎整个墙,从而O(n2) 的复杂度),如下图:
比较
不用多想,我们可以非常明显的知道,思路二思路是非常清晰的,很明了,然而边界问题可能会有点坑爹,队友在这个上面坑了一个多小时依旧GG,而第一种思路则非常巧妙,前提得知道单调栈,单调栈其实非常好理解,不会的读者可以百度学习一下,分分钟钟的事情,然后就是这种方法基本不用考虑什么边界问题,直接就是左边加右边即可完成,属于第二种思路的逆向思维
代码
#include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 1e5 + 5;const int INF = 0x3f3f3f3f;typedef long long LL;typedef pair<int, int> PII;vector<PII> w;int n, o[MAXN];int dpl[MAXN], dpr[MAXN];void solve(int *dp, int l, int r) { int d = l <= r ? 1 : -1; w.clear(); for(int i = l; i != r; i += d) { PII in(0, l); //单调栈部分(可以用stack实现,也可以用其他,方法各异) while(w.size() && w.back().first <= o[i]) { in = max(in, w.back()); w.pop_back(); } if(w.size()) in = max(in, w.back()); while(!w.size() || w.back().first > o[i]) { w.push_back(PII(o[i], i)); } //单调栈部分 dp[i] = dp[in.second] + (i - in.second) * min(o[i], in.first) * d; }}int main() { int _; scanf("%d", &_); while(_ --) { scanf("%d", &n); for(int i = 1; i <= n; i ++) { scanf("%d", &o[i]); } memset(dpl, 0, sizeof(dpl)); memset(dpr, 0, sizeof(dpr)); solve(dpl, 1, n + 1); solve(dpr, n, 1 - 1); int maxv = INF; for(int i = 1; i <= n - 1; i ++) { maxv = min(dpl[i] + dpr[i + 1], maxv); } printf("%d\n", dpl[n] - maxv); } return 0;}/************************************************************** Problem: 1838 User: 24862486 Language: C++ Result: AC Time:92 ms Memory:2520 kb/****************************************************************/
1 0
- CSU-ACM 1838: Water Pump(单调栈+前缀后缀和)
- 文章标题 CSU 1838: Water Pump (单调栈)
- CSU 1838: Water Pump(ACM-ICPC Asia Thailand National On-Site Programming Contest 2015)
- POJ - 3415 Common Substrings 后缀数组+单调栈+前缀和
- [ACM] hdu 5147 Sequence II (树状数组,前缀和,后缀和)
- 后缀数组 CSU - 1598 最长公共前缀
- [UVa 1619] Feel Good (单调栈+前缀和)
- ACM水题--字符串的前缀和后缀
- Feel Good (前缀和+单调队列)
- 前缀和后缀和
- CSU 1809: Parenthesis【前缀和】
- 前缀++和后缀++
- 前缀和后缀表达式
- 前缀、中缀和后缀
- 前缀++和后缀++
- CSU 1809 Parenthesis(线段树前缀和)
- [BZOJ3879]SvT(后缀数组+单调栈)
- spoj-3415(后缀数组+单调栈)
- 深度学习之GoogleNet and ResNet
- ssh的配置
- Javascript闭包
- EChars学习笔记(二)之快速建立项目
- HTML网页开发手册
- CSU-ACM 1838: Water Pump(单调栈+前缀后缀和)
- 浅谈 Vue v-model指令的实现原理
- 端口与进程
- 解决CC2540 XDATA内存不足
- JVM进阶(十二)——JAVA 可视化分析工具
- ASP.NET中 ValidationGroup[控件的属性]:分组验证的使用
- swiper简单使用2
- java同步方法和同步代码块
- 水仙花数