[UVA1619]Feel Good[DP]

来源:互联网 发布:网络律师 编辑:程序博客网 时间:2024/05/01 16:28
题目链接:[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;}

0 0
原创粉丝点击