Loading

POJ 2796:Feel Good(单调栈)

http://poj.org/problem?id=2796

题意:给出n个数,问一个区间里面最小的元素*这个区间元素的和的最大值是多少。

思路:只想到了O(n^2)的做法。

参考了http://www.cnblogs.com/ziyi--caolu/archive/2013/06/23/3151556.html的写法,用单调栈可以优化到O(n)。

对于每个元素,维护这个元素向前延伸比它大的有多少个,向后延伸比它小的有多少个。即该元素是处于山谷。

那么如何用单调栈维护这个呢?

首先这个栈是单调递增的,对于当前栈顶的元素top,如果比要进栈的元素now大,那么是top要出栈,那么top出栈后的栈顶元素suftop一定比top小,那么代表着suftop可以向后延伸到top的向后延伸位置,因为入栈元素now一定比top小,那么now可以向前延伸到top向前延伸的位置。

预处理一个前缀和,当元素出栈的时候就可以直接计算了。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <stack>
 5 using namespace std;
 6 #define N 100010
 7 typedef long long LL;
 8 struct node {
 9     int pre, suf, id;
10     LL num;
11 } p[N];
12 LL sum[N];
13 
14 void solve(int n) {
15     for(int i = 1; i <= n; i++) {
16         scanf("%lld", &p[i].num);
17         p[i].pre = p[i].suf = 1; p[i].id = i;
18         sum[i] = sum[i-1] + p[i].num;
19     }
20     LL ans = -1; int l, r; // 有0这个坑点
21     stack<node> sta;
22     sta.push(p[1]);
23     for(int i = 2; i <= n; i++) {
24         while(!sta.empty() && sta.top().num > p[i].num) {
25             node top = sta.top(); sta.pop();
26             if(!sta.empty()) sta.top().suf += top.suf;
27             p[i].pre += top.pre;
28             LL res = sum[top.id + top.suf - 1] - sum[top.id - top.pre];
29             res *= top.num;
30             if(res > ans) {
31                 ans = res;
32                 l = top.id - top.pre + 1;
33                 r = top.id + top.suf - 1;
34             }
35         }
36         sta.push(p[i]);
37     }
38     while(!sta.empty()) {
39         node top = sta.top(); sta.pop();
40         if(!sta.empty()) sta.top().suf += top.suf;
41         LL res = sum[top.id + top.suf - 1] - sum[top.id - top.pre];
42         res *= top.num;
43         if(res > ans) {
44             ans = res;
45             l = top.id - top.pre + 1;
46             r = top.id + top.suf - 1;
47         }
48     }
49     printf("%lld\n%d %d\n", ans, l, r);
50 }
51 
52 int main() {
53     int n;
54     while(~scanf("%d", &n)) solve(n);
55     return 0;
56 }

 

posted @ 2017-03-04 13:09  Shadowdsp  阅读(290)  评论(0编辑  收藏  举报