2016百度之星初賽Astar Round2B
阿新 • • 發佈:2019-02-18
題意:
定義一個區間的價值為區間的最大數*最小數。現給了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; }