同南昌网络赛,贴过来改改直接过了。
因为不单调,所以不能直接尺取,分治的话可以拿脚写。放宽了时限所以可以接受nlogn的复杂度。
本来直接for是不单调的,但是如果规定分治中点mid,那么过mid往两侧延伸的最小值单调递减,过mid往两侧延伸的前缀和的前缀最大值与前缀最小值也是单调的。
凭空造了两个单调出来,所以可以划窗尺取。分成两种情况,即假设最小值由左侧提供,假设最小值由右侧提供。
最大值只要么由当前对面可结合的前缀和中最大的提供,要么就是最小的提供,所以两种都和当前答案取max即可。
#include <bits/stdc++.h> using namespace std; const int MAXN=3000005; struct node { long long sum; long long mn; } templ[MAXN],tempr[MAXN]; long long a[MAXN],b[MAXN],ans,lsufmax[MAXN],lsufmin[MAXN],rsufmax[MAXN],rsufmin[MAXN]; int n; void div_algorithm(int l,int r) { if(l==r) { ans=max(ans,a[l]*b[l]); return; } int mid=(l+r)>>1; int ln=0,rn=0; ++ln; templ[ln].mn=a[mid]; templ[ln].sum=b[mid]; for(int i=mid-1; i>=l; --i) { ++ln; templ[ln].mn=min(templ[ln-1].mn,a[i]); templ[ln].sum=templ[ln-1].sum+b[i]; ans=max(ans,templ[ln].sum*templ[ln].mn); } ++rn; tempr[rn].mn=a[mid+1]; tempr[rn].sum=b[mid+1]; ans=max(ans,tempr[rn].mn*tempr[rn].sum); for(int i=mid+2; i<=r; ++i) { ++rn; tempr[rn].mn=min(tempr[rn-1].mn,a[i]); tempr[rn].sum=tempr[rn-1].sum+b[i]; ans=max(ans,tempr[rn].sum*tempr[rn].mn); } reverse(templ+1,templ+1+ln); reverse(tempr+1,tempr+1+rn); lsufmax[ln]=templ[ln].sum; lsufmin[ln]=templ[ln].sum; for(int i=ln-1; i; --i) { lsufmax[i]=max(lsufmax[i+1],templ[i].sum); lsufmin[i]=min(lsufmin[i+1],templ[i].sum); } rsufmax[rn]=tempr[rn].sum; rsufmin[rn]=tempr[rn].sum; for(int i=rn-1; i; --i) { rsufmax[i]=max(rsufmax[i+1],tempr[i].sum); rsufmin[i]=min(rsufmin[i+1],tempr[i].sum); } int nowp=1; for(int i=1; i<=ln; ++i) { while(nowp<=rn&&tempr[nowp].mn<templ[i].mn)++nowp; if(nowp>rn)break; ans=max(ans,templ[i].mn*(templ[i].sum+rsufmin[nowp])); ans=max(ans,templ[i].mn*(templ[i].sum+rsufmax[nowp])); } nowp=1; for(int i=1; i<=rn; ++i) { while(nowp<=ln&&templ[nowp].mn<tempr[i].mn)++nowp; if(nowp>ln)break; ans=max(ans,tempr[i].mn*(tempr[i].sum+lsufmin[nowp])); ans=max(ans,tempr[i].mn*(tempr[i].sum+lsufmax[nowp])); } div_algorithm(l,mid); div_algorithm(mid+1,r); } int main() { while(scanf("%d",&n)!=EOF) { for(int i=1; i<=n; ++i) { scanf("%lld",&a[i]); } for(int i=1; i<=n; ++i) { scanf("%lld",&b[i]); } ans=-(1LL<<62); div_algorithm(1,n); printf("%lld\n",ans); } return 0; }