POJ

来源:互联网 发布:js 数组值存在 编辑:程序博客网 时间:2024/06/06 19:45

点我看题

题意:给你n个数,让求某一连续子序列的和乘以其中子序列中的最小值的乘积最大.

分析:可以直接把每个数看成一个正方形,然后求这些正方形组合起来的最大矩形面积.可以单调栈解决这个问题,但是在计算的时候,要先求得前n项的和,找到每个数对应的区间之后,再利用尺取法求长度,最后求乘积,否则会TLE.

参考代码:

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<stack>#include<iostream>using namespace std;typedef long long ll;const int maxn = 1e5+10;ll n;ll a[maxn];ll l[maxn],r[maxn];ll sum[maxn];int main(){while( ~scanf("%lld",&n)){sum[0] = 0;for( int i = 1; i <= n; i++){scanf("%lld",&a[i]);sum[i] = sum[i-1]+a[i];//printf("sum=%lld\n",sum[i]);}stack<ll> s;for( int i = 1; i <= n; i++){while( !s.empty() && a[i] <= a[s.top()])s.pop();if( !s.empty())l[i] = s.top()+1;elsel[i] = 1;s.push(i);}while( !s.empty())s.pop();for( int i = n; i >= 1; i--){while( !s.empty() && a[i] <= a[s.top()])s.pop();if( !s.empty())r[i] = s.top()-1;elser[i] = n;s.push(i);}ll ans = 0;ll p=1,q=1;for( int i = 1; i <= n; i++){ll tmp = (sum[r[i]]-sum[l[i]-1])*a[i];//printf("l=%lld r=%lld suml=%lld sumr=%lld a=%lld tmp=%lld\n",l[i],r[i],sum[l[i]-1],sum[r[i]],a[i],tmp);if( tmp > ans){ans = tmp;p = l[i];q = r[i];}}printf("%lld\n%lld %lld\n",ans,p,q);}return 0;}