「ICPC WF 2017」不劳而获的钱财 Money for Nothing
题意转化为:给出在平面直角坐标系上的若干个左下角和右上角,求组成的最大矩形面积。
那么对于 $ \exists B , X_A \le X_B$ 且 \(Y_A \le Y_B\) 的左下角 \(B\) 点显然无意义,右上角类似。
然后按 \(x\) 坐标排序,对于相邻的两个左下角 $A_1 , A_2 (X_{A_1} < X_{A_2}) $ 和右上角 \(B_1 , B_2 (X_{B_1} < X_{B_2})\) ,我们发现如果 \(A_1\) 的最优决策点在 \(B_1\) 之后,那么对 \(A_2\) 来说 \(B_2\) 也一定比 \(B_1\) 更优,于是得知决策点是单调的,分治求答案即可。时间复杂度 \(O(n \log n)\) 。
#include<bits/stdc++.h>
#define fo(i,a,b) for(register int i=a;i<=b;++i)
#define fd(i,a,b) for(register int i=a;i>=b;--i)
#define gc() (BB == BE ? (BE = (BB = BUFF) + fread(BUFF,1,BUFF_SIZE,stdin),BB == BE ? EOF : *BB++) : *BB++)
const int BUFF_SIZE = 1 << 20;
char BUFF[BUFF_SIZE],*BB,*BE;
#define ll long long
using namespace std;
const int N=5e5+10;
const ll INF=0x3f3f3f3f3f3f;
int n,m,cnt1,cnt2,cnt;
ll ans,Min,Max;
struct node{
ll x,y;
}a[N],b[N],c[N],d[N];
inline bool cmp(node a,node b){return a.x<b.x || (a.x==b.x && a.y<b.y);}
inline bool cmp1(node a,node b){return a.x>b.x || (a.x==b.x && a.y>b.y);}
inline ll calc(int x,int y){
return (b[y].x-a[x].x) * (b[y].y - a[x].y);
}
void solve(int l,int r,int L,int R){
int mid=l+r>>1;ll ret=-INF,w=0;
fo(i,L,R){
if(b[i].y<=a[mid].y){
if(w)break;
if(l<mid)solve(l,mid-1,L,i);
if(mid<r)solve(mid+1,r,i,R);
return;
}
ll cur=calc(mid,i);
if(cur>ret){
ret=cur;
w=i;
}
}
ans=max(ans,ret);
if(l<mid)solve(l,mid-1,L,w);
if(mid<r)solve(mid+1,r,w,R);
}
inline int read(){
int t=0;
char ch=gc();
while(ch<'0' || '9'<ch)ch=gc();
while('0'<=ch && ch<='9'){
t=t*10+ch-'0';
ch=gc();
}
return t;
}
int main(){
m=read();n=read();
fo(i,1,m)
c[i].x=read(),c[i].y=read();
sort(c+1,c+m+1,cmp);
fo(i,1,n)
d[i].x=read(),d[i].y=read();
sort(d+1,d+n+1,cmp1);
Min=INF;Max=-INF;
fo(i,1,m){
if(c[i].y<Min){
Min=c[i].y;
a[++cnt1]=c[i];
}
}
fo(i,1,n){
if(d[i].y>Max){
Max=d[i].y;
b[++cnt2]=d[i];
}
}
n=cnt1;m=cnt2;
sort(b+1,b+m+1,cmp);
solve(1,n,1,m);
printf("%lld\n",ans);
return 0;
}