2016百度之星初赛Astar Round2B - 区间的价值

来源:互联网 发布:电脑上的编程软件 编辑:程序博客网 时间:2024/04/30 02:05

题意:

定义一个区间的价值为区间的最大数*最小数。现给了n(1n100000)个数,问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 longusing 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;}


0 0