CSU-ACM 1838: Water Pump(单调栈+前缀后缀和)

来源:互联网 发布:淘宝上比较好的女装 编辑:程序博客网 时间:2024/05/29 17:56

特记

专为某人写的题解,记住哟,要思考思考

题意

给你n个墙壁,墙壁中间是一些房子村庄,然后就是老天开始下雨了,将墙壁之间的空隙给填满了,一句话:就是发洪灾啦,然后呢,政府需要泄洪,于是在这些墙壁之间打通一个下水管,将这里的水给排出去,最后问打通哪里的下水管能够排出去的水最多,输出最终结果

解题思路

  1. 思路一
    如果当前我们选择i处开通下水管,那么最终的状态就是,左边的水都会满,右边的水都会满,而i处的水都会被放掉,那么遵循这个思路,我们先运用单调栈保存到当前位置距离i最近并且比i处的墙高或者最接近i高度的墙的位置在哪里,如下图:这里写图片描述
    然后从左边求一遍以1为起点以i为终点,这之间水填满时的水量为dpl[i],同理从右边求一遍dpr[i],最终的答案就是=min{dpl[i]+dpr[i+1]}

  2. 思路二
    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
原创粉丝点击