#include <iostream>
#include <stdlib.h>
#include <stdio.h>
/*
Reference:http://www.cnblogs.com/youngxiao/archive/2010/05/19/1739381.html.THX A LOT TO YOU.
author:YuXun Lu(A.K.A Kyle Broflovlaski)
problem:poj2796
Begin Time:13:00 p.m. 2/18/2012
End Time: About 4 hours after that
Test Data:
6
3 1 6 4 5 2
7
7 6 5 4 3 2 1
9
5 4 3 2 1 2 3 4 5
Summary:
思路和剪枝真的很重要。
这道题明显是一个思路上的优化就从TLE变成了ACCEPT
还有一个重点就是cin和cout在效率方面跟printf和scanf差异巨大。
以上。
思路:
设元素1....n,元素值v[1]...v[n],起始区间s[1]...s[n],结束区间e[1]..e[n]
本题就是找到以元素i的元素值v[i]为最小值的一个区间。
因为
Happy Value : 区间元素值的和*区间最小元素值
所以区间一定要最长,朴素的搜索一定会爆时间,我们可以采取如下策略剪枝:
1.对于元素i,读入元素i的元素值v[i],令j = i - 1;
WHILE (j>0)
IF v[i] < v[j] THEN
j = s[j] - 1
ELSE
s[i] = j + 1
ENDIF
ENDW
这就获得了v[i]的起始地址,因为如果v[j] > v[i]的话
那么v[j]对应的区间[s[j]...e[j]]肯定其中所有元素都比v[i]大
因为v[j]是其中最小的元素,我们把s[j]向左移动一个与s[i]比较,如果小于的话
那么该元素又成为了新的v[j],如果大于的话移动回来就可以了。
对于结束地址,也是一样
WHILE(j <= n+1)
IF v[i] < v[j] THEN
j = e[j] + 1
ELSE
e[i] = j - 1
ENDIF
ENDW
但是注意到这个算法需要v[i]以1开始
边界条件为v[0] = -1;v[n+1] = -1;否则根据条件,s[i]和e[i]取不到1和n;
我们还要维护一个“和表”,其值为
sum[n] = v[1] + v[2] + v[3] ... + v[n]
这个简单,读取完了之后直接加到里面就行了。
最终输出结果
res = max(sum[e[i]] - sum[s[i] - 1] ) * v[i] );
然后再输出s[i],e[i]就可以了。
*/
using namespace std;
const long MAXSIZE = 100010 ;
long long v[MAXSIZE];
long long s[MAXSIZE];
long long e[MAXSIZE];
long long sum[MAXSIZE];
int main()
{
long n;
// freopen("b:\\acm\\poj2796\\input.txt","r",stdin);
//while(cin >> n)
while(scanf("%d",&n) == 1)
{ long long maxv = -1;
long p,q;
v[n+1] = -1;
sum[0] = 0;
s[0] = 1;
v[0] = -1;
for(int i = 1 ; i <= n ; i++)
{
int j ;
//cin >> v[i];
scanf("%d",&v[i]);
j = i - 1;
while( j >= 0 )
{
if( v[i] > v[j])
{
s[i] = j + 1;
break;
}
else
//v[i] > v[j]
{
j = s[j] - 1;
}
}
sum[i] = sum[i-1] + v[i];
}
for(int i = n; i > 0 ; i--)
{
int j ;
j = i + 1;
while( j <= n + 1)
{
if(v[i] > v[j])
{
e[i] = j - 1;
break;
}
else
{
j = e[j] + 1;
}
}
}
for(int i = 1; i <= n ; i ++)
{
if(v[i]*(sum[e[i]] - sum[s[i]-1]) > maxv)
{
maxv = v[i]*(sum[e[i]] - sum[s[i]-1]);
p = s[i];
q = e[i];
}
}
//cout << maxv << endl;
//cout << p << " " << q << endl;
printf("%I64d\n",maxv);
printf("%d %d",p,q);
}
// cout << "Hello world!" << endl;
return 0;
}
【POJ2796】代码,非原创,参考的别人的文章
最新推荐文章于 2021-03-22 00:12:22 发布