#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】代碼,非原創,參考的別人的文章
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.