题解:CF1638F Two Posters
george0929 · · 题解
讨论矩形的横坐标区间关系,分为不交、包含和交错。
其中不交直接暴力即可。
考虑包含的情况,容易发现其等价于在第
容易通过调整法发现此时下方的矩形的上边界应该尽可能靠上。因此下方矩形只有
考虑交错的情况,考虑枚举两个矩形横坐标的并
由此可以得出
记
约束条件:
不难发现最优解必定卡满不等式的至少两个上界,假设确定了
由于卡到
第一种情况:卡到
此时对于一个
预处理每个
对固定的
第二种情况:卡到
此时对于一个
预处理每个
考虑优化枚举
因此只需要枚举
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
ll h[10005],ans;
int lst[10005],nxt[10005];
int st[10005],tp;
void init(){
for(int i=1;i<=n;i++){
while(tp&&h[st[tp]]>h[i]){
nxt[st[tp]]=i-1;
st[tp--]=0;
}
st[++tp]=i;
}
while(tp) nxt[st[tp]]=n,st[tp--]=0;
for(int i=n;i>=1;i--){
while(tp&&h[st[tp]]>h[i]){
lst[st[tp]]=i+1;
st[tp--]=0;
}
st[++tp]=i;
}
while(tp) lst[st[tp]]=1,st[tp--]=0;
}
ll calc(int l,int r,ll k=0){//计算h[l,r]-k的最大矩形面积
if(l>r) return 0;
ll res=0;
for(int i=l;i<=r;i++){
res=max(res,1ll*(min(r,nxt[i])-max(l,lst[i])+1)*(h[i]-k));
}
return res;
}
ll tmpA[10005],tmpB[10005],suf[10005];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>h[i];
init();
for(int i=1;i<=n;i++) ans=max(ans,calc(1,i)+calc(i+1,n));
for(int i=1;i<=n;i++) ans=max(ans,calc(lst[i],nxt[i],h[i])+h[i]*(nxt[i]-lst[i]+1));
for(int i=1;i<=n;i++){
ll mn=h[i];
int L=lst[i],R=nxt[i];
if(L==1||R==n) continue;
//A+B<=mn
ll A=mn;
for(int l=L-1;l>=1;l--){
A=min(A,h[l]);
tmpA[l]=A;
}
ll B=mn;
for(int r=R+1;r<=n;r++){
B=min(B,h[r]);
tmpB[r]=B;
}
for(int r=n;r>=1;r--){
suf[r]=max(suf[r+1],(r-L+1)*tmpB[r]);
}
int r=R+1;
for(int l=1;l<=L-1;l++){//A,B
while(r<=n&&tmpA[l]+tmpB[r]>mn) r++;
if(r>n) break;
ans=max(ans,1ll*(R-l+1)*tmpA[l]+suf[r]);
}
r=R;
for(int l=1;l<=L-1;l++){//A,A+B
while(r+1<=n&&mn-tmpA[l]<=tmpB[r+1]) r++;
if(r>R) ans=max(ans,1ll*(R-l+1)*tmpA[l]+1ll*(r-L+1)*(mn-tmpA[l]));
}
int l=L;
for(int r=n;r>=R+1;r--){//A+B,B
while(l-1>=1&&mn-tmpB[r]<=tmpA[l-1]) l--;
if(l<L) ans=max(ans,1ll*(R-l+1)*(mn-tmpB[r])+1ll*(r-L+1)*tmpB[r]);
}
}
cout<<ans<<"\n";
return 0;
}