POJ 2796 Feel Good

来源:互联网 发布:中南大学刘路 知乎 编辑:程序博客网 时间:2024/05/06 16:38

单调栈的应用,也可以用DP来做,DP具体做法与这篇类似。http://blog.csdn.net/wangjie_wang/article/details/9864917

这里用单调栈求出以每个点为最小值的左右边界,最后遍历一次取最大值就可以了。

#include <cstdio>#include <cstring>#include <string>#include <iostream>#include <map>#include <vector>#include <cmath>#include <stack>#include <queue>#include <cstdlib>#include <algorithm>using namespace std;typedef __int64 int64;typedef long long ll;#define M 100005#define N 1000005#define max_inf 0x7f7f7f7f#define min_inf 0x80808080#define mod 1000000007ll n , top;ll q[M] , arr[M] , sum[M] , lef[M] , rig[M];void Solve(){ll i , ret , l , r;ret = -(1<<30);top = 0;for (i = 1 ; i <= n ; i++){while (top > 0 && arr[q[top-1]] > arr[i]){rig[q[top-1]] = i-1;top--;}q[top++] = i;}while (top)rig[q[top-1]] = n,top--;for (i = n ; i >= 1 ; i--){while (top > 0 && arr[q[top-1]] > arr[i]){lef[q[top-1]] = i+1;top--;}q[top++] = i;}while (top)lef[q[top-1]] = 1,top--;for (i = 1 ; i <= n ; i++){ll temp = (sum[rig[i]]-sum[lef[i]-1])*arr[i];if (ret < temp){ret = temp;l = lef[i];r = rig[i];}}printf("%lld\n%lld %lld\n",ret,l,r);}int main(){ll i;while (~scanf("%lld",&n)){for (sum[0] = 0 , i = 1 ; i <= n ; i++){scanf("%lld",arr+i);sum[i] = sum[i-1]+arr[i];}Solve();}return 0;}