1.题目描述:
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 14381 | Accepted: 3976 | |
Case Time Limit: 1000MS | Special Judge |
Description
A new idea Bill has recently developed assigns a non-negative integer value to each day of human life.
Bill calls this value the emotional value of the day. The greater the emotional value is, the better the daywas. Bill suggests that the value of some period of human life is proportional to the sum of the emotional values of the days in the given period, multiplied by the smallest emotional value of the day in it. This schema reflects that good on average period can be greatly spoiled by one very bad day.
Now Bill is planning to investigate his own life and find the period of his life that had the greatest value. Help him to do so.
Input
Output
Sample Input
6 3 1 6 4 5 2
Sample Output
60 3 5
Source
2.题意概述:给你一段区间,需要你求出(在这段区间之类的最小值*这段区间所有元素之和)的最大值
例如:
6 3 1 6 4 5 2
以4为最小值,向左右延伸,6 4 5 值为60
3.解题思路:
考虑对于每个点以它为最小值向两边延伸的最大长度,遇到大于它(小于它)的值,就将它延伸的范围扩大,一般来说,要这样做的算法复杂度为o(n^2)。但是借助栈这个玩意,维护其单调增(减),就可以在o(n)的时间复杂度解决这个问题。将一元素加入栈时,先判断它是否大于(小于)栈顶元素,若是大于(小于)栈顶元素,加入栈。(从这里开始只讲维护单调增栈)否则,将栈顶元素出栈,直到栈顶元素小于要加入栈的元素,在此过程中,需要维护向前延伸和向后延伸的问题,当要加入栈的元素之前有n个栈元素出栈,那么说明这n个出栈的元素都会大于或者等于要入栈的元素,此时,我们需要维护入栈元素可以向前延伸多少个元素(相当于记录它的前面有多少个元素比它大),而每个栈顶元素要向出栈了的元素延伸,因为在出栈了的元素一定是比它的大的元素(根据我维护的是单调增栈)......这样,就在o(n)的时间复杂度内解决了上述问题.........
例如:3 1 6 4 5 2
(3,1,1) (1,2,2) (6,3,3) (4,4,4) (5,5,5) (2,6,6)
首先每个元素自己本身的前后延伸都为1,把3加入栈,1<3,把3出栈,用1的前延伸加上3的前延伸,如此变为(1,1,2),6<1,入栈,变成(1,1,2)(6,3,3),
4<6,将6出栈,4向前延伸,1向后延伸变成(1,1,3) (4,3,4)
5>4,入栈,变成(1,1,3)(4,3,4)(5,5,5)
2<5,5出栈,2向前延伸,4向后延伸,变成(1,1,3)(4,3,5) 2还未入栈(2,5,6)
2<4,4出栈,2向前延伸,1向后延伸,变成(1,1,5) (2,3,6).....
一次类推,会发现最大的结果在(4,3,5)这里这意味着,以4为最小值的区间范围为3————5,也就是6 4 5
4.AC代码:#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <functional>
#include <cmath>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#define INF 0x3f3f3f3f
#define maxn 100100
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r - t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
int q[maxn], a[maxn], dp[maxn];
ll sum[maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long _begin_time = clock();
#endif
int n;
while (~scanf("%d", &n))
{
sum[0] = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
dp[i] = i;
sum[i] = sum[i - 1] + a[i];
}
ll ans = -1;
int l, r, top = 0;
a[++n] = -1;
dp[n] = 0;
for (int i = 1; i <= n; i++)
{
if (top == 0 || a[i] > a[q[top - 1]])
q[top++] = i;
else if (a[i] == a[q[top - 1]])
dp[i] = dp[q[top - 1]];
else
{
while (top > 0 && a[i] < a[q[top - 1]])
{
top--;
ll tmp = a[q[top]] * (sum[i - 1] - sum[dp[q[top]] - 1]);
if (tmp > ans)
{
ans = tmp;
l = dp[q[top]];
r = i - 1;
}
}
dp[i] = dp[q[top]];
q[top++] = i;
}
}
printf("%lld\n%d %d\n", ans, l, r);
}
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time = %ld ms.", _end_time - _begin_time);
#endif
return 0;
}