题意:
定义一个区间的价值为区间的最大数*最小数。现给了n(1≤n≤100000)个数,问1~n长度的最大价值分别是多少。
题解:
用两个线段树以及快排的思想可以在O(nlog(n))的时间解决该题。
首先用线段树找到一个区间[L,R]的最小值位置为a与最大值位置为b,[L,R]中所有包含[a,b]的区间的价值都为A[a]*A[b]。然后对[L,a-1],[a+1,R]重复这个过程。
Code:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include<ctime>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
const int MAXN=100005;
ll MAX[MAXN<<2],MIN[MAXN<<2],A[MAXN],ANS[MAXN];
void updateMAX(int x,int l,int r,int now){
if (l==r){
MAX[now]=l;
return;
}
int mid=(l+r)>>1;
if (x<=mid) updateMAX(x,l,mid,now<<1);
else updateMAX(x,mid+1,r,(now<<1)|1);
if (A[MAX[now<<1]]>A[MAX[now<<1|1]]) MAX[now]=MAX[now<<1];
else MAX[now]=MAX[now<<1|1];
}
void updateMIN(int x,int l,int r,int now){
if (l==r){
MIN[now]=l;
return;
}
int mid=(l+r)>>1;
if (x<=mid) updateMIN(x,l,mid,now<<1);
else updateMIN(x,mid+1,r,(now<<1)|1);
if (A[MIN[now<<1]]<A[MIN[now<<1|1]]) MIN[now]=MIN[now<<1];
else MIN[now]=MIN[now<<1|1];
}
int queryMAX(int l,int r,int L,int R,int now)
{
if (l>=L && r<=R) return MAX[now];
int mid=(l+r)>>1,a=0,b=0;
if (L<=mid) a=queryMAX(l,mid,L,R,now<<1);
if (R>mid) b=queryMAX(mid+1,r,L,R,now<<1|1);
if (a==0) return b;
if (b==0) return a;
if (A[a]>A[b]) return a;
return b;
}
int queryMIN(int l,int r,int L,int R,int now)
{
if (l>=L && r<=R) return MIN[now];
int mid=(l+r)>>1,a=0,b=0;
if (L<=mid) a=queryMIN(l,mid,L,R,now<<1);
if (R>mid) b=queryMIN(mid+1,r,L,R,now<<1|1);
if (a==0) return b;
if (b==0) return a;
if (A[a]<A[b]) return a;
return b;
}
void dfs(int l,int r,int n){
if (r<l) return;
int a=queryMAX(1,n,l,r,1),b=queryMIN(1,n,l,r,1);
if (a>b) swap(a,b);
ll d=A[a]*A[b];
for (int i=(b-a+1);i<=(r-l+1);i++)
ANS[i]=max(ANS[i],d);
if (A[b]>A[a]) dfs(a+1,r,n),dfs(l,a-1,n);
else dfs(b+1,r,n),dfs(l,b-1,n);
}
int main()
{
int n;
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
while (~scanf("%d",&n)){
memset(MAX,0,sizeof(MAX));
memset(MIN,0,sizeof(MIN));
for (int i=1;i<=n;i++){
scanf("%I64d",&A[i]);
updateMAX(i,1,n,1);
updateMIN(i,1,n,1);
}
memset(ANS,0,sizeof(ANS));
dfs(1,n,n);
for (int i=1;i<=n;i++)
printf("%I64d\n",ANS[i]);
}
return 0;
}