美丽的序列(洛谷 2659)

题目背景

GD是一个热衷于寻求美好事物的人,一天他拿到了一个美丽的序列。

题目描述

为了研究这个序列的美丽程度,GD定义了一个序列的“美丽度”和“美丽系数”:对于这个序列的任意一个区间[l,r],这个区间的“美丽度”就是这个区间的长度与这个区间的最小值的乘积,而整个序列的“美丽系数”就是它的所有区间的“美丽度”的最大值。现在GD想要你帮忙计算这个序列的“美丽系数”。

输入输出格式

输入格式:

第一行一个整数n,代表序列中的元素个数。 第二行n个整数a1、a2„an,描述这个序列。

输出格式:

一行一个整数,代表这个序列的“美丽系数”。

输入输出样例

输入样例#1

3 
1 2 3

输出样例#1

4

说明

样例解释 选取区间[2,3],可以获得最大“美丽系数”为2*2=4。 数据范围 对于20%的数据,n<=2000; 对于60%的数据,n<=200000; 对于100%的数据,1<=n<=2000000,0<=ai<=2000000。 提示 你可能需要一个读入优化。

/*
  思路没问题,但有点小技巧
  我枚举的最小值,然后由它向两边扩展,然后就超时了
  AC代码也是这样写的,不过它是记录了i的最右端和最左端,然后类似于DP,
  省了很多重复计算。 
*/
#include<cstdio>
#include<iostream>
#define N 2000010
#define INF 1000000000
#define ll long long
using namespace std;
int a[N],zuo[N],you[N],n;
int read()
{
    int num=0,flag=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*flag;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
      a[i]=read();
    a[0]=a[n+1]=-INF;
    for(int i=n;i>=1;i--)
    {
        if(a[i]>a[i+1])you[i]=i;
        else
        {
            int j=i;
            while(a[j+1]>=a[i])
              j=you[j+1];
            you[i]=j;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(a[i]>a[i-1])zuo[i]=i;
        else
        {
            int j=i;
            while(a[j-1]>=a[i])j=zuo[j-1];
            zuo[i]=j;
        }
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
      ans=max(ans,1LL*(you[i]-zuo[i]+1)*a[i]);
    cout<<ans;
    return 0;
}
View Code

 

posted @ 2016-10-04 21:51  karles~  阅读(544)  评论(0编辑  收藏  举报