(POJ 2796) Feel Good

Feel Good

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)。文件的其余部分包含n个整数a1,a2,… (0 ≤ ai ≤1000000)表示每一天的情感价值,数字由空格或换行符分隔。

  • 输出

在第一行打印出比尔一生中某个时期的最大价值。在第二行打印两个数字l和r,这样比尔生命的第 l 天到第 r 天(包括第 l 天和第 r 天)的时间段具有最大的可能值。如果存在具有最大可能值的多个期间,则打印其中任何一个期间。

样例如上

一个so经典的单调栈 + 前缀数组
a[ i ] 存每一天的情感价值
首先很明确的我们要比较的是以 ai 为最小值时它的左右期间的和与 ai 的乘积
l 数组和 r 数组用来存期间,最后用前缀数组的差得到期间内的和,然后进行比较
那么难点就是我们怎么知道 ai 的左右区间
这里我们就要用到单调栈,可以看一下代码里的注释帮助理解

#include <cstdio>
#include <iostream>
#include <stack>
#define maxn 100010

using namespace std;
typedef long long ll;

int a[maxn], l[maxn], r[maxn];
ll sum[maxn];
stack <ll> st;
int main() {
  int n, key;
  ll max, num;
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i) {
    scanf("%d", &a[i]);
    sum[i] = sum[i-1] + a[i]; //个人习惯从1开始存
  }
  sum[++n] = -1;//别人教我的,为了保证给最小值一个右区间
  st.push(1);
  l[1] = 1; //从第一个开始比较
  for(int i = 2; i <= n; i++) {//首先要明确的是我们入栈的是下标
    while(!st.empty() && a[st.top()] >= a[i]) {
      r[st.top()] = i - 1;//如果a[st.top()] >= a[i],那么显然a[st.top()]的右区间到此为止了
      st.pop();
    }//继承之前a[st.top()]的左区间,因为那些值都大于等于a[st.top()]
    if(st.empty()) l[i] = 1;//队列为空说明前面没有比它小的,直接继承到开始为止 
    else l[i] = st.top() + 1;//否则说明前面有比它小的,继承到开始为止比它小的位置下标+1 
    st.push(i);
  }
  max = sum[r[1]] * a[1];//定一个最大值
  key = 1;
  for(int i = 1; i < n; i++) {
    num = (sum[r[i]] - sum[l[i]-1]) * a[i];
    if (num >= max)  {
      key = i;
      max = num;
    }
  }
  printf("%lld\n%d %d\n", max,l[key], r[key]);
  return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值