zoukankan      html  css  js  c++  java
  • POJ 2796 Feel Good(单调栈)

    题目的大致意思是,给你n个数,我们需要计算一个值,这个值是这个序列中的一段连续的子序列里的最小值*这段这段连续子序列的和,我们要使得求得的这个值最大,比如样例6 3 1 6 4 5 2,我们选择6 4 5这段连续的子序列,值为4*(6+4+5)=60。

    首先对于每个数a[i],我们想让他最大可能的往左右扩展,知道这个数往左和往右最大的扩展的坐标l,r,利用前缀和我们就求得了这个值a[i]*(s[r]-s[l-1]),所以这题在于我们怎么去求一个数往左右扩展的最大位置,

    我们先以往右扩展为例,用R[i]表示i往右扩展的最大位置。我们建立一个单调栈,这个单调栈是单调递减的,即栈顶到栈顶递减,用数组表示即是从左到右递增。我们扫描这个序列。

    如果当前这个数比栈顶大或者等于,我们直接入栈。

    如果当前这个数比栈顶小,我们就从栈中弹出,直到这个数比栈顶大,那怎么记录往右扩展的最大位置呢,我们在把数从栈中弹出的过程中,弹出的数一定比当前要入栈的数大,因此他一定不是最小的数,对后面没有作用,因此弹出的数最大扩展位置就是当前这个数的位置i再减去1,即i-1

    我们用pos数组记录一下栈中数所在的位置,同时a[n+1]设为-1,保证最后栈中元素都可以被弹出。

    向左扩展也是一样道理。

    #include <iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 10;
    int a[N], n, L[N], R[N], s[N], tot, pos[N];
    ll sum[N];
    pair<int, int> ans;
    int main()
    {
        cin >> n;
        for (int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
            sum[i] = sum[i - 1] + 1LL*a[i];
            L[i] = R[i] = i;
        }
        a[n + 1] = -1;
        for (int i = 1; i <= n+1; i++)
        {
            if (a[i] >= s[tot])
                s[++tot] = a[i],pos[tot]=i;
            else{
                while (tot&&a[i] < s[tot]){
                    R[pos[tot]] = i - 1;
                    tot--;
                }
                s[++tot] = a[i],pos[tot]=i;
            }
        }
        a[0] = -1,tot=0;
        for (int i = n; i >= 0; i--){
            if (a[i] >= s[tot]){
                s[++tot] = a[i],pos[tot]=i;
            }
            else{
                while (tot&& a[i] < s[tot]){
                    L[pos[tot]] = i+1;
                    tot--;
                }
                s[++tot] = a[i], pos[tot] = i;
            }
        }
        ll max_val= -1;
        for (int i = 1; i <= n; i++){
            if (a[i]*(sum[R[i]] - sum[L[i] - 1]) > max_val)
            {
                max_val = a[i] * (sum[R[i]] - sum[L[i] - 1]);
                ans.first = L[i];
                ans.second = R[i];
            }
        }
        cout << max_val << endl;
        cout << ans.first << " " << ans.second << endl;
        return 0;
    }
  • 相关阅读:
    简单的REST的框架实现
    将 Shiro 作为一个许可为基础的应用程序 五:password加密/解密Spring应用
    Java自注三进入
    hdu 4803 贪心/思维题
    SSH框架总结(框架分析+环境搭建+实例源代码下载)
    Rational Rose 2007 &amp;Rational Rose 2003 下载及破解方法和汉化文件下载
    hdu 5014 思维题/推理
    电脑蓝屏出现事件7000
    大豆生物柴油驱动的大巴斯(Bus)
    POJ 3481 &amp; HDU 1908 Double Queue (map运用)
  • 原文地址:https://www.cnblogs.com/xiaoguapi/p/10578180.html
Copyright © 2011-2022 走看看