用单调栈维护所管辖的区间左端和右端 并用线段树维护前缀和

//#pragma comment(linker, "/STACK:102400000,102400000") #include "bits/stdc++.h" #define pb push_back #define ls l,m,now<<1 #define rs m+1,r,now<<1|1 #define hhh printf("hhh ") #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) using namespace std; typedef long long ll; typedef pair<int,int> pr; inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;} const int N=3e6+10; struct node { int l,r; ll maxx,minn; }tree[N<<2]; ll sum[N],a[N]; ll b[N]; int n; int l[N],r[N]; void pushup(int cur) { tree[cur].maxx=max(tree[cur<<1].maxx,tree[cur<<1|1].maxx); tree[cur].minn=min(tree[cur<<1].minn,tree[cur<<1|1].minn); } void build(int l,int r,int cur) { tree[cur].l=l; tree[cur].r=r; if(l==r) { tree[cur].maxx=tree[cur].minn=sum[l]; return; } int mid=(r+l)>>1; build(l,mid,cur<<1); build(mid+1,r,cur<<1|1); pushup(cur); // cout<<l<<" "<<r<<" "<<tree[cur].l<<" "<<tree[cur].maxx<<" "<<tree[cur].minn<<endl; } ll querymax(int pl,int pr,int cur) { if(pl<=tree[cur].l&&tree[cur].r<=pr) { return tree[cur].maxx; } ll res=-1e18; if(pl<=tree[cur<<1].r) res=max(res,querymax(pl,pr,cur<<1)); if(pr>=tree[cur<<1|1].l) res=max(res,querymax(pl,pr,cur<<1|1)); return res; } ll querymin(int pl,int pr,int cur) { if(pl<=tree[cur].l&&tree[cur].r<=pr) { return tree[cur].minn; } ll res=1e18; if(pl<=tree[cur<<1].r) res=min(res,querymin(pl,pr,cur<<1)); if(pr>=tree[cur<<1|1].l) res=min(res,querymin(pl,pr,cur<<1|1)); return res; } int main() { n=read(); for(int i=1;i<=n;++i) { scanf("%lld", &b[i]); } for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); sum[i]=sum[i-1]+a[i]; } stack<int> s; for(int i=1;i<=n;i++) { while(!s.empty() && b[s.top()] >= b[i]) s.pop(); if(s.empty()) l[i]=0; else { l[i]=s.top(); } s.push(i); // cout<<l[i]<<endl; } while(!s.empty()) s.pop(); for(int i=n;i>=1;i--) { while(!s.empty() && b[s.top()] >= b[i]) s.pop(); if(s.empty()) r[i]=n; else r[i]=s.top()-1; // cout<<r[i]<<endl; s.push(i); } build(0,n,1); ll ans=-1e18,cnt; for(int i=1;i<=n;i++) { cnt=b[i]; // cout<<l[i]<<" "<<i-1<<" "<<i<<" "<<r[i]<<endl; if(cnt>0) cnt=cnt*(querymax(i,r[i],1)-querymin(l[i],i-1,1)); else cnt=cnt*(querymin(i,r[i],1)-querymax(l[i],i-1,1)); // cout<<cnt<<endl; ans=max(ans,cnt); } printf("%lld ",ans); return 0; }