Problem Description
我们定义“区间的价值”为一段区间的最大值*最小值。
一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1)。
现在聪明的杰西想要知道,对于长度为k的区间,最大价值的区间价值是多少。
当然,由于这个问题过于简单。
我们肯定得加强一下。
我们想要知道的是,对于长度为1∼n的区间,最大价值的区间价值分别是多少。
样例解释:
长度为1的最优区间为2−2 答案为6∗6
长度为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 }
AC代码
时间: 2024-10-06 05:55:09