zoukankan      html  css  js  c++  java
  • POJ 2796 Feel Good 【单调栈】

    传送门http://poj.org/problem?id=2796

    题意:给你一串数字,需要你求出(某个子区间乘以这段区间中的最小值)所得到的最大值

    例子:

    6
    3 1 6 4 5 2 

    L=3,R=5时这段区间总和为6+4+5=15,最小值为4,所以最后的结果为60.

    思路:单调栈的板子题了。没学过单调栈的我只能现学了。单调栈分为单调递增栈,单调递减栈。而这个题呢,要用到单调递增栈。怎么维护单调栈呢?那就是在遇到一个元素大于栈顶元素时,就将该元素加入栈中。(假定a_i即为区间最小值,区间左端点L=i,区间右端点R=i)如果遇到一个小于栈顶的元素时,则把栈里面的元素弹出来,同时记录该元素向左延申的最大长度,即更新区间左端点。在弹出栈顶元素时把这个要弹出栈的元素(栈顶元素)的右端点赋值给这个它的下一个元素(当前栈中次大元素),即更新区间右端点,同时更新答案。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn = 1e6 + 10;
    struct node
    {
        int l;
        int r;
        long long num;
    } s[maxn];
    long long a[maxn];
    long long sum[maxn];
    long long ans;
    int ans_l;
    int ans_r;
    int top;
    int n;
    void solve(int top)
    {
        int l = s[top].l;
        int r = s[top].r;
        //更新答案
        if((sum[r] - sum[l - 1])*s[top].num >= ans)
        {
            ans = (sum[r] - sum[l - 1]) * s[top].num;
            ans_r = r;
            ans_l = l;
        }
        //向右延申
        if(top > 0)
        {
            s[top - 1].r = s[top].r;
        }
    }
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
        {
            scanf("%I64d", &a[i]);
            //记录前缀和
            sum[i] = a[i] + sum[i - 1];
        }
        top = -1;
        for(int i = 1; i <= n; i++)
        {
            //初始假定a[i]为区间最小值,左区间,右区间都为i
            node v;
            v.l = i;
            v.r = i;
            v.num = a[i];
            //加入的元素大于栈顶元素向左延申
            while(top != -1 && s[top].num >= a[i])
            {
                solve(top);
                //一直向左更新 ,直到某一个元素小于加入的元素
                v.l = s[top].l;
                top--;
            }
            s[++top].l = v.l;
            s[top].r = v.r;
            s[top].num = a[i];
        }
        //单调栈中元素可能不为空
        while(top != -1)
        {
            solve(top);
            top--;
        }
        cout << ans << endl;
        cout << ans_l << " " << ans_r << endl;
    }
  • 相关阅读:
    FileDescriptor详解
    java序列化
    ObjectInputStream和ObejctOutputStream
    ByteArrayOutputStream
    ByteArrayInputStream
    PipedInputStream/PipedOutputStream
    字节输入流
    反义
    贪婪和非贪婪
    MYSQL数据库优化
  • 原文地址:https://www.cnblogs.com/yyaoling/p/12260424.html
Copyright © 2011-2022 走看看