Problem Descriptionide
咱們定義「區間的價值」爲一段區間的最大值*最小值。測試
一個區間左端點在L,右端點在R,那麼該區間的長度爲(R−L+1)。spa
如今聰明的傑西想要知道,對於長度爲k的區間,最大價值的區間價值是多少。code
固然,因爲這個問題過於簡單。blog
咱們確定得增強一下。ip
咱們想要知道的是,對於長度爲1∼n的區間,最大價值的區間價值分別是多少。io
樣例解釋:event
長度爲1的最優區間爲2−2 答案爲6∗6class
長度爲2的最優區間爲4−5 答案爲4∗4效率
長度爲3的最優區間爲2−4 答案爲2∗6
長度爲4的最優區間爲2−5 答案爲2∗6
長度爲5的最優區間爲1−5 答案爲1∗6
Input
多組測試數據
第一行一個數n(1≤n≤100000)。
第二行n個正整數(1≤ai≤10^9),下標從1開始。
因爲某種不可抗力,ai的值將會是1∼10^9內隨機產生的一個數。(除了樣例)
Output
輸出共n行,第i行表示區間長度爲i的區間中最大的區間價值。
Sample Input
5
1 6 2 4 4
Sample Output
36
16
12
12
6
看見那鮮紅的隨機產生了嗎?顯然這是突破口(當時看着不少人A然而並無想出來
其實對於隨機數據,有些暴力的效率很高
咱們枚舉每個點做爲區間的最大值(因此大於這個值的都不能取),而後向兩邊擴展,擴展的順序是將較大者加入區間,邊作邊更新答案
貪心的正確性算比較顯然吧,較大值加進來確定比較小值加進來優,由於最大值已經固定了,咱們要讓最小值最大
1 #include<cstdio> 2 using namespace std; 3 4 int a[100100],n; 5 long long ans[100100]; 6 7 void work() 8 { 9 for(int i = 1;i <= n;i++) 10 scanf("%d",&a[i]); 11 for(int i = 1;i <= n;i++) 12 ans[i]=0; 13 14 for(int i = 1;i <= n;i++) 15 { 16 long long max=a[i],min=a[i]; 17 int len=1,l=i,r=i; 18 while(1) 19 { 20 if(ans[len]<max*min)ans[len]=max*min; 21 if(l==1 || a[l-1]>max) 22 if(r==n || a[r+1]>max) break; 23 else 24 { 25 r++; 26 len++; 27 if(a[r]<min)min=a[r]; 28 } 29 else 30 if(r==n || a[r+1]>max) 31 { 32 l--; 33 len++; 34 if(a[l]<min)min=a[l]; 35 } 36 else 37 { 38 if(a[l-1]>a[r+1]) 39 { 40 l--; 41 len++; 42 if(a[l]<min)min=a[l]; 43 } 44 else 45 { 46 r++; 47 len++; 48 if(a[r]<min)min=a[r]; 49 } 50 } 51 } 52 } 53 54 for(int i = 1;i <= n;i++) 55 printf("%I64d\n",ans[i]); 56 } 57 58 int main(){ 59 while(scanf("%d",&n)!=EOF) 60 work(); 61 return 0; 62 }