同南昌网络赛,贴过来改改直接过了。
因为不单调,所以不能直接尺取,分治的话可以拿脚写。放宽了时限所以可以接受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; }