区间的价值
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1366 Accepted Submission(s): 608
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
一个区间左端点在 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≤109) ,下标从 1 开始。
由于某种不可抗力, ai 的值将会是 1∼109 内<b style="color:red;">随机产生</b>的一个数。(除了样例)
第一行一个数 n(1≤n≤100000) 。
第二行 n 个正整数 (1≤ai≤109) ,下标从 1 开始。
由于某种不可抗力, ai 的值将会是 1∼109 内<b style="color:red;">随机产生</b>的一个数。(除了样例)
Output
输出共
n
行,第
i
行表示区间长度为
i
的区间中最大的区间价值。
Sample Input
5 1 6 2 4 4
Sample Output
36 16 12 12 6
Source
思路:这题思路比较巧妙,参考了别人的做法:大致是枚举最小值,每次更新必须包含此最小值的区间,显然有ans[i]=max(ans[i], ans[i+1]),因为数据随机,不会退化到O(n^2)。
# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 1e5+30;
LL a[maxn], ans[maxn];
void dfs(int l, int r)
{
if(l >= r) return;
int minid=0, maxid=0;
for(int i=l; i<=r; ++i)
{
if(minid==0||a[i]<a[minid]) minid = i;
if(maxid==0||a[i]>a[maxid]) maxid = i;
}
ans[r-l+1] = max(ans[r-l+1], a[minid]*a[maxid]);
dfs(l, minid-1);
dfs(minid+1, r);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(ans, 0, sizeof(ans));
for(int i=1; i<=n; ++i)
{
scanf("%lld",&a[i]);
ans[1] = max(ans[1], a[i]*a[i]);
}
dfs(1, n);
for(int i=n-1; i>1; --i) ans[i] = max(ans[i], ans[i+1]);
for(int i=1; i<=n; ++i) printf("%lld\n",ans[i]);
}
return 0;
}