题目链接:
[UVA1619]Feel Good[DP]
题意分析:求一个连续区间的最大值。定义:区间最大值 = 区间和 * 区间最小数。
具体代码如下:
题意分析:求一个连续区间的最大值。定义:区间最大值 = 区间和 * 区间最小数。
解题思路:根据区间最大值的定义,我们可以枚举每个区间然后进行计算。然而显然是要超时的。这时可以考虑将每个数作为最小值,求出以其为最小值的区间的左值和右值。
以左值的更新为例:当当前值大于等于区间最小值时我们就向左更新,可以发觉,当前值如果比区间最小值大,那么以当前值作为最小值的区间的左值,当前区间肯定也能到达。
eg. 4 3 2 1 4 5 。以1为最小值的区间[1,6]。当更新的时候我们更新到左边的2,以2为最小值的区间为[1,3]这时就可以直接更新到1。这道题要注意下0存在的情况,特判下,另外有多个相同值需要输出最短的区间。
个人感受:这道题和 [HDU1506]Largest Rectangle in a Histogram[dp] 差不多,当时思维被固定了。听他们谈起线段树就以为是线段树才能解。。。。哎,感觉越来越不爱思考了T T具体代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + 111;
typedef long long ll;
int v[MAXN];
ll sum[MAXN], l[MAXN], r[MAXN];
int main()
{
int n;
int cnt = 0;
while( cin >> n )
{
ll ansl = 0, ansr = 0, ansv = -1;
memset(sum , 0, sizeof sum);
for(int i = 0; i < n; ++i) cin >> v[i], l[i] = r[i] = i;
for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + v[i - 1]; //记录前n项和
for(int i = 0; i < n; ++i) //更新左值
{
while(v[i] != 0 && l[i] > 0 && v[l[i] - 1] >= v[i])
l[i] = l[l[i] - 1];
}
for(int i = n - 1; i >= 0; --i)//更新右值
{
while(v[i]!= 0 && r[i] < n - 1 && v[r[i] + 1] >= v[i]) //小心为0的情况,这时不进行更新区间
r[i] = r[r[i] + 1];
}
for(int i = 0; i < n; ++i)
{
ll temp = (sum[r[i] + 1] - sum[l[i]]) * v[i];
if( temp > ansv )
{
ansv = temp;
ansl = l[i] + 1;
ansr = r[i] + 1;
}
else if(temp == ansv && ansr - ansl > r[i] - l[i]) //注意题目条件
{
ansl = l[i] + 1;
ansr = r[i] + 1;
}
}
if(cnt++) cout << '\n';
cout << ansv << '\n' << ansl << ' ' << ansr << '\n';
}
return 0;
}