Feel Good

Feel Good

Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 114   Accepted Submission(s) : 31
Special Judge
Problem 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 10<sup>6</sup> - 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个数,让你找出某一连续子段,相加得和,然后乘以该子段中最小数。让你求一个最大值。

      咋一看起来无从下手,其实我们可以把这个题化抽象为形象,图形化来表示。在这之前先看看这一道题:点击打开链接

      ok,看完了之后,想一想,本题的意思是不是给你n个底边为a[i],高也为a[i]的矩形排成一排,让你求一个可以分割出来的最大矩形呢?做法和那个题一样,单调栈求每一个点向左向右第一个小于自己的地方,用个乘法求出每次矩阵,找出最大值就好了。

      注意一点:求底边边长的时候直接加超时!!!要开始用个sum数组保存每个点的坐标(即求和),相减求底边。超时原因,想一想1000000个数,全都一样高,最后你每个点都要从1加到n一次,时间复杂度不就n^2了吗。

代码如下:

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
long long int a[100010];
long long int sum[100010];
int l[100010];
int r[100010];
int s[100010];
int main()
{
	int N;
	int top;
	while(cin>>N && N)
	{
	    memset(sum,0,sizeof(sum));
	    int flag=0;
        for(int i=1;i<=N;i++)
		{
			scanf("%I64d",&a[i]);
			l[i]=i;
			r[i]=i;
			sum[i]=sum[i-1]+a[i];
			if(flag==0)
            {
                if(sum[i]>0)
                    flag=1;
            }
		}
		if(flag==0)
        {
            printf("0\n1");
            printf(" %d\n",N);
            continue;
        }
		top=0;
		for(int i=1;i<=N;i++)   //向左找
		{
			while(top && a[i]<=a[s[top]])
                top--;
            if(top==0)
                l[i]=1;
            else
                l[i]=s[top]+1;//s[top]存的数的值肯定是比a[i]小的,所以地s[top]+1个位置即为所求
            s[++top]=i;
		}
		top=0;
		for(int i=N;i>=1;i--)
		{
			while(top && a[i]<=a[s[top]])
                top--;
            if(top==0)
                r[i]=N;
            else
                r[i]=s[top]-1;
            s[++top]=i;
		}
		long long int maxn=0;
		long long int area;
		int ll=0,rr=0;
		for(int i=1;i<=N;i++)
		{
		    area=0;
		    area=sum[r[i]]-sum[l[i]-1];//求和   循环超时
			area*=a[i];
			if(maxn<area)
            {
                maxn=area;
                ll=l[i];
                rr=r[i];
            }
		}
		printf("%I64d\n",maxn);
		printf("%d %d\n",ll,rr);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值