「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;
}