zoukankan      html  css  js  c++  java
  • 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
    %d %d
    ", ans, l, r);
    50 }
    51 
    52 int main() {
    53     int n;
    54     while(~scanf("%d", &n)) solve(n);
    55     return 0;
    56 }
  • 相关阅读:
    AngularJS指令的详解
    Linux(Ubuntu)下如何安装JDK
    Hibernate的三种状态
    JS是按值传递还是按引用传递
    git分支管理
    Hibernate注解映射联合主键的三种主要方式
    Linux下解决用户不能执行sudo的方法
    【GStreamer开发】GStreamer基础教程03——动态pipeline
    【GStreamer开发】GStreamer基础教程02——GStreamer概念
    【GStreamer开发】GStreamer基础教程02——GStreamer概念
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6501094.html
Copyright © 2011-2022 走看看