本题坑点比较多
注意:①特判都是输入0的情况
②是多组数据数据
这题在uva上提交总是WA,原因是uva其实没有special judge,实际要输出长度最短且最偏左的子序列。
所以我就到poj做了。。
注意到,对于数列中的一个数a,只有向其左右两端不断扩展,直到遇到比它小的数为止,这段区间即是以a为最小值的区间。因此枚举1-n的每个数为区间的最小值。剩下的任务就是怎么找到当前这个数左右两边小于它的数。
找左边的做法=找右边的做法
找出一个数左边第一个比它小的数,即是单调栈模板题。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
int stk[N], top;
LL a[N], sum[N];
int n;
int l[N], r[N];
int main()
{
int suc = 0;
while(scanf("%d", &n) != - 1)
{
a[0] = a[n + 1] = 0;
for (int i = 1; i <= n; i ++)
{
scanf("%lld", &a[i]);
if (a[i]) suc = 1;
sum[i] = a[i] + sum[i - 1];
}
if (!suc)
{
cout << 0 << endl;
cout << 1 << ' ' << 1;
puts("");
continue;
}
for (int i = 0; i <= n; i ++)
{
while(top && a[stk[top]] >= a[i]) top --;
l[i] = stk[top];
stk[++ top] = i;
}
top = 0;
for (int i = n + 1; i >= 1; i --)
{
while(top && a[stk[top]] >= a[i]) top --;
r[i] = stk[top];
stk[++ top] = i;
}
int L, R;
LL res= -1;
for (int i = 1; i <= n; i ++)
{
if (res < a[i] * (sum[r[i] - 1] - sum[l[i]]))
L = l[i] + 1, R = r[i] - 1;
res = max(res, a[i] * (sum[r[i] - 1] - sum[l[i]]));
}
printf("%lld\n", res);
printf("%d %d\n", L, R);
}
}