zoukankan      html  css  js  c++  java
  • POJ 2796: Feel Good

    题意:

    一个数组,对于某个区间,这个区间的和*这个区间中的最小值=这个区间的计算值。求这个数组中的最大计算值,并任意输出其的一个左右位置。

    思路:

    维护一个最小单调栈。
    对于某个元素:
    如果被弹出了,说明它最多向右延伸到这里。
    对于进栈,如果它的进栈没有造成任何元素的弹出,则说明它的位置就是它左边能延伸到的位置。如果造成元素弹出,那么,最后一个弹出的元素的左边能延伸到的位置就是本元素往左能延伸到的位置。
    对于两个元素相同时:我不作弹出处理,仅仅把这个元素的位置更新(代码中表现为把这个元素往左延伸的和更新)。

    在弹出元素时,能求和,而这个和正是元素往右延伸的和。往左延伸的和已经算好,所以这个元素为最小值的最大区间值就可以知道了。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <utility>
    using namespace std;
    #define N 110000
    
    #define PLL pair<long long ,long long>
    #define MP(a,b) make_pair(a,b)
    int a[N];
    int n;
    PLL st[N];
    int lst[N];
    int top;
    
    void solve() {
        a[n] = -1;
    
        top = 0;
        long long ans = -1;
        int l = 0, r = 0;
        int i;
        st[top] = MP(0,a[0]); // minnum, presum
        lst[top] = 0;
        top++;
        for (i = 1; i <= n; i++) {
            long long sum = 0;
            bool ispop = false;
            while (top && a[st[top-1].first] > a[i]) {
                sum += st[top-1].second;
                if (ans < sum * a[st[top-1].first]) {
                    l = lst[top-1];
                    r = i-1;
                    ans = sum * a[st[top-1].first];
                }
                top--;
                ispop = true;
            }
            if (top && a[st[top-1].first] == a[i]) {
                st[top-1].second += sum + a[i];
            } else {
                st[top] = MP(i, sum+a[i]);
                if (!ispop) lst[top] = i;
                top++;
            }
        }
        printf("%lld
    %d %d
    ", ans, l+1, r+1);
    }
    
    int main() {
        while (~scanf("%d", &n)) {
            int i;
            for (i = 0;i < n; i++) {
                scanf("%d", &a[i]);
            }
            solve();
        }
        return 0;
    }
    View Code

    思路2(看别人的):

    维护单调栈,元素被弹栈的时候,就是它能延伸到的最远点。从左到右和从右到左来两次,得到一个元素左延伸最远值和右延伸最远值,就可以得到这个元素为最小值的区间最大计算值。

    代码:

    #include <algorithm>
    #include <cstdio>
    #include<string.h>
    using namespace std;
    
    const int maxn=100010;
    
    int a[maxn],q[maxn];
    long long s[maxn];
    int lft[maxn],rht[maxn];
    int main()
    {
        int n,i,j,k;
    
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
    
        a[0]=a[n+1]=-2100000000;
    
        int r=0;
        for(i=1;i<=n+1;i++)
        {
            while(r&&a[q[r]]>a[i])
                rht[q[r]]=i,r--;
            q[++r]=i;
        }
        r=0;
        for(i=n;i>=0;i--)
        {
            while(r&&a[q[r]]>a[i])
                lft[q[r]]=i,r--;
            q[++r]=i;
        }
        for(i=1;i<=n;i++)
            s[i]=s[i-1]+a[i];
        long long ans=-1;
        int l;
        for(i=1;i<=n;i++)
        {
            if(ans<(s[rht[i]-1]-s[lft[i]])*a[i])
                ans=max(ans,(s[rht[i]-1]-s[lft[i]])*a[i]),l=lft[i]+1,r=rht[i]-1;
        }
        printf("%I64d
    %d %d
    ",ans,l,r);
    }
    View Code
  • 相关阅读:
    网络安全法课程上线喽~
    网络安全法将在六一正式实施,我该如何继续爱你?
    安卓逆向入门(一)
    如何正确的使用Ubuntu以及安装常用的渗透工具集.
    Linux/CentOS各种服务框架的搭建完整流程
    【Anroid界面实现】WindowManager类使用具体解释——用户首次打开APP的使用教学蒙板效果实现
    2014年辛星jquery解读第三节 Ajax
    迅为4412开发板Linux驱动教程/硬件知识及原理图的使用
    点评国内各大在线app生成平台
    OpenGL ES2.0 基本编程
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3456725.html
Copyright © 2011-2022 走看看