题目连接 :
http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1772
题目类型:
动态规划 - 最优子段
数据结构:
struct LMIC_ARR
{
__int64 vle;
/* 记录arr[i]的左界和右界 */
int s, e;
};
思路分析:
动态规划思想, 不过个人觉得比较像暴力,
输入一串数列,arr : a1,a2,a3......an
记录每一个 ai 大于等于它的 左右界,
直接用2次for 中间加while 左右循环的找
直到找到比ai小的数字停止.就是它的界
最后选取个最大值的 右界-左界 * 它自身的数值 就是答案
---------------------------------------------------------------------------
我想到这个方法的时候觉得会超时 所以没敢试,
但从网上得来的代码证明, 这样不会超时, 我也不知道为什么
理论来说 最坏时间 应该是 N^2
证明:
类似暴力破解, 证明 略
源代码:
#include <iostream>
#include <stdio.h>
using namespace std;
struct LMIC_ARR
{
__int64 vle;
/* 记录arr[i]的左界和右界 */
int s, e;
};
int main()
{
int i, n, tmp;
LMIC_ARR arr[100005];
while( scanf( "%d", &n ), n )
{
for( i = 1; i <= n; i ++ )
{
scanf( "%I64d", &arr[i].vle );
tmp = i;
if( tmp == 1 )
{
arr[i].s = 1;
}
else
{
while( tmp > 1 && arr[i].vle <= arr[tmp - 1].vle )
{
tmp = arr[tmp - 1].s;
}
arr[i].s = tmp;
}
}
for( i = n ; i >= 1; i -- )
{
tmp = i;
if( tmp == n )
{
arr[i].e = n;
}
else
{
while( tmp < n && arr[i].vle <= arr[tmp + 1].vle )
{
tmp = arr[tmp + 1].e;
}
arr[i].e = tmp;
}
}
__int64 max = -1;
for( i = 1; i <= n ; i ++ )
{
__int64 snt = ( arr[i].e - arr[i].s + 1 ) * arr[i].vle;
max >?= snt;
}
printf( "%I64d\n", max );
}
return 0;
}