套路题
求出来以每个数为最大值/最小值时的一个区间范围, 然后枚举每个数为最大值的情况更新即可, 但是对于重复数的话需要特判一下, 假如用map记录来特判复杂度就是$O(nlogn)$, 不过题目说了数据随机, 数字几乎不重复, 没特判直接跑了Rank2
#include <iostream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #include <map> #include <queue> #include <string> #include <string.h> #define REP(i,a,n) for(int i=a;i<=n;++i) #define PER(i,a,n) for(int i=n;i>=a;--i) #define hr putchar(10) #define pb push_back #define lc (o<<1) #define rc (lc|1) #define mid ((l+r)>>1) #define ls lc,l,mid #define rs rc,mid+1,r #define x first #define y second #define io std::ios::sync_with_stdio(false) #define endl '\n' using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N = 1e6+10; int n; int a[N], b[N], L[N], R[N], LL[N], RR[N]; ll ans[N]; void chkmax(ll &x, ll y) {x=max(x,y);} void work() { REP(i,1,n) scanf("%d", a+i); REP(i,1,n) ans[i]=0; REP(i,1,n) { LL[i]=L[i]=i-1; while (L[i]&&a[i]>=a[L[i]]) L[i]=L[L[i]]; while (LL[i]&&a[i]<=a[LL[i]]) LL[i]=LL[LL[i]]; } PER(i,1,n) { RR[i]=R[i]=i+1; while (R[i]<=n&&a[i]>=a[R[i]]) R[i]=R[R[i]]; while (RR[i]<=n&&a[i]<=a[RR[i]]) RR[i]=RR[RR[i]]; } REP(i,1,n) { pii mi(a[i],i); PER(j,L[i]+1,i-1) { mi = min(mi, pii(a[j],j)); chkmax(ans[RR[mi.y]-j],(ll)mi.x*a[i]); } mi = pii(a[i],i); REP(j,i+1,R[i]-1) { mi = min(mi, pii(a[j],j)); chkmax(ans[j-LL[mi.y]],(ll)mi.x*a[i]); } } REP(i,1,n) ans[1]=max(ans[1],(ll)a[i]*a[i]); PER(i,1,n) ans[i]=max(ans[i],ans[i+1]); REP(i,1,n) printf("%lld\n",ans[i]); } int main() { for (; ~scanf("%d", &n); ) work(); }