区间的价值
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 662 Accepted Submission(s): 329
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
首先回顾一下快排的思想:快排每次划分,都是从随机找一个值作为阀值(简单起见,通常找第一个),然后从需要划分的区间的最右端找比阀值小的值,用这个值去填最左端那个位置,从最左端找比阀值大的值,用这个值填最右端那个位置,交替去找,知道low和high相等,然后将阀值放到该位置,这次划分结束,阀值左边的值都比阀值右边的值要小。递归排序阀值左边的区间和右边的区间,最终保证有序。
这个题目要求的是区间长度为i的区间中最小值和最大值的乘积的最大值。我们拿到一段区间l, r,假设这段区间中的最小值的位置为idmin,最大值的位置为idmax,这段区间中的所有区间长度大于等于abs(idmin-idmax)+1的区间都可以被a[idmin]*a[idmax]更新到,由于我们要的是最大值,所以我们以最小值为分隔,递归求解左部分和右部分,都不能包含分隔。
#include<stdio.h> #include<algorithm> #include<string.h> #include<math.h> #include<string> #include<iostream> #include<queue> #include<stack> #include<map> #include<vector> #include<set> using namespace std; typedef long long LL; #define mid (L+R)/2 #define lson rt*2,L,mid #define rson rt*2+1,mid+1,R #pragma comment(linker, "/STACK:102400000,102400000") const int maxn = 1e5+300; const int INF = 0x3f3f3f3f; typedef long long LL; typedef unsigned long long ULL; struct Seg{ LL val, Min, Max; int idmin, idmax; }segs[maxn*4]; LL a[maxn]; LL ans[maxn]; int n; void PushUP(int rt){ segs[rt].Max = max(segs[rt*2].Max,segs[rt*2+1].Max); segs[rt].Min = min(segs[rt*2].Min,segs[rt*2+1].Min); if(segs[rt*2].Max > segs[rt*2+1].Max) segs[rt].idmax = segs[rt*2].idmax; else segs[rt].idmax = segs[rt*2+1].idmax; if(segs[rt*2].Min < segs[rt*2+1].Min) segs[rt].idmin = segs[rt*2].idmin; else segs[rt].idmin = segs[rt*2+1].idmin; } void buildtree(int rt,int L,int R){ if(L == R){ segs[rt].val = a[L]; segs[rt].idmax = segs[rt].idmin = L; segs[rt].Min = segs[rt].Max = a[L]; return; } buildtree(lson); buildtree(rson); PushUP(rt); } int querymin(int rt,int L,int R,int l_ran,int r_ran){ if(l_ran<=L&&R<=r_ran){ return segs[rt].idmin; } int id = 0; if(l_ran <= mid){ id = querymin(lson,l_ran,r_ran); } if(r_ran > mid){ int tid = querymin(rson,l_ran,r_ran); if(id != 0){ if(a[id] > a[tid]) id = tid; }else{ id = tid; } } return id; } int querymax(int rt,int L,int R,int l_ran,int r_ran){ if(l_ran<=L&&R<=r_ran){ return segs[rt].idmax; } int id = 0; if(l_ran <= mid){ id = querymax(lson,l_ran,r_ran); } if(r_ran > mid){ int tid = querymax(rson,l_ran,r_ran); if(id != 0){ if(a[id] < a[tid]) id = tid; }else{ id = tid; } } return id; } void dfs(int l, int r){ if(l > r) return; int idmin, idmax; idmin = querymin(1,1,n,l,r); idmax= querymax(1,1,n,l,r); if(idmax < idmin) swap(idmin,idmax); LL tmp = a[idmax]*a[idmin]; for(int i = idmax-idmin+1; i <= r-l+1; i++){ ans[i] = max(ans[i], tmp); } if(a[idmax] > a[idmin]){ dfs(l,idmin-1); dfs(idmin+1,r); }else{ dfs(l,idmax-1); dfs(idmax+1,r); } } int main(){ while(scanf("%d",&n)!=EOF){ LL ret = 0; for(int i = 1; i <= n; i++){ scanf("%lld",&a[i]); } buildtree(1,1,n); for(int i = 1; i <= n; ++i){ ans[i] = 1; } dfs(1,n); for(int i = 1; i <= n; i++){ printf("%lld ",ans[i]); } } return 0; } /* 5 5 1 2 4 4 */