加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

UVA1619 感觉不错 Feel Good

发布时间:2020-12-14 05:10:34 所属栏目:大数据 来源:网络整理
导读:Description Bill is developing a new mathematical theory for human emotions. His recent investigations are dedicated to studying how good or bad days influent people‘s memories about some period of life. A new idea Bill has recently devel

Description

Bill is developing a new mathematical theory for human emotions. His recent investigations are dedicated to studying how good or bad days influent people‘s memories about some period of life.

A new idea Bill has recently developed assigns a non-negative integer value to each day of human life.

Bill calls this value the emotional value of the day. The greater the emotional value is,the better the daywas. Bill suggests that the value of some period of human life is proportional to the sum of the emotional values of the days in the given period,multiplied by the smallest emotional value of the day in it. This schema reflects that good on average period can be greatly spoiled by one very bad day.

Now Bill is planning to investigate his own life and find the period of his life that had the greatest value. Help him to do so.

Input

The first line of the input contains n - the number of days of Bill‘s life he is planning to investigate(1 <= n <= 100 000). The rest of the file contains n integer numbers a1,a2,... an ranging from 0 to 106 - the emotional values of the days. Numbers are separated by spaces and/or line breaks.

Output

Print the greatest value of some period of Bill‘s life in the first line. And on the second line print two numbers l and r such that the period from l-th to r-th day of Bill‘s life(inclusive) has the greatest possible value. If there are multiple periods with the greatest possible value,then print any one of them.

Sample Input

6

3 1 6 4 5 2

Sample Output

60

3 5

题意翻译

题目大意: 给出正整数n和一个(1 <= n <= 100 000)长度的数列,要求找出一个子区间,使这个子区间的数字和乘上子区间中的最小值最大。输出这个最大值与区间的两个端点。

思路:

要对每一个节点进行扩展,这样扩展的话,复杂度是O(n^2)。减少时间复杂度要用单调栈,单调栈处理的问题就是对每一个节点进行扩展的问题,这个题目要维护的是一个单调递减栈,即从栈顶元素到栈底元素,值是单调递减的,即栈顶元素的值始终是栈的最大值。然后每一个值有属于自己的区间,这个区间目的是为了记录之后的元素向前延伸的用处。

向后延伸就靠从1到n扫描元素,(维护单调递减栈)这样当扫描的元素大于栈顶元素时,直接入栈。

当扫描的元素等于栈顶元素时,不记录,只将区间延伸到后面。

当扫描的元素小于栈顶元素时,这时要计算栈内当前的值。因为扫描的元素时小于栈顶元素的,要求的是一个区间的最小值,所以栈内那些大于该元素的值你会发现没有用处了,只需要将它们的那些区间留下来就对了,这就是向前扩展。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=100010;

int st[N],top;
int a[N],lef[N];
int n,ansl,ansr;
long long sum[N];
long long tmp,ans;

int main () {
    ans=-1;
    scanf("%d",&n);
    memset(sum,sizeof(sum));
    for(int i=1; i<=n; i++) {
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    a[++n]=-1;
    top=0;
    for(int i=1; i<=n; i++) {
        if(top==0||a[i]>a[st[top-1]]) {
            st[top++]=i;
            lef[i]=i;
            continue;
        }
        if(a[i]==a[st[top-1]])
            continue;
        while(top>=1&&a[i]<a[st[top-1]]) {
            --top;
            tmp=(long long)a[st[top]]*(sum[i-1]-sum[lef[st[top]]-1]);
            if(tmp>ans) {
                ansl=lef[st[top]];
                ansr=i-1;
                ans=tmp;
            }
        }
        lef[i]=lef[st[top]];
        st[top++]=i;
    }
    printf("%lldn%d %dn",ans,ansr);
    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读