bzoj 4578 [Usaco2016 OPen]Splitting the Field

本文提供了一道USACO竞赛题目“Splitting the Field”的解决方案,该题要求用两个矩形最小化覆盖所有点的面积总和,并确保两个矩形不重叠。文章详细介绍了通过坐标排序和遍历来找到最优解的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


4578: [Usaco2016 OPen]Splitting the Field

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 105   Solved: 46
[ Submit][ Status][ Discuss]

Description

Farmer John's N cows (3≤N≤50,000) are all located at distinct positions in his two-dimensional fie
ld. FJ wants to enclose all of the cows with a rectangular fence whose sides are parallel to the x a
nd y axes, and he wants this fence to be as small as possible so that it contains everycow (cows on 
the boundary are allowed).FJ is unfortunately on a tight budget due to low milk production last quar
ter. He would therefore like to enclose a smaller area to reduce maintenance costs, and the only way
 he can see to do this is by building two enclosures instead of one. Please help him compute how muc
h less area he needs to enclose, in total, by using two enclosures instead of one. Like the original
 enclosure, the two enclosures must collectively contain all the cows (with cows on boundaries allow
ed), and they must have sides parallel to the x and y axes. The two enclosures are notallowed to ove
rlap -- not even on their boundaries. Note that enclosures of zero area are legal, for example if an
 enclosure has zero width and/or zero height.

Input

The first line of input contains N. The nextNN lines each contain two integers specifying the location of a cow. Cow locations are positive integers in the range 1…1,000,000,000

Output

Write a single integer specifying amount of total area FJ can save by using two enclosures instead o
f one.

Sample Input

6
4 2
8 10
1 1
9 12
14 7
2 3

Sample Output

107

HINT

Source





【分析】

签到题...

大意:给二维坐标系中的n个点,求ans=用一个矩形覆盖所有点所用矩形面积-用两个矩形覆盖所有点所用两个矩形的最小面积和,而且两个矩形不能重合(边重合也不行)

手玩可知,两个矩形一定是一个在左边,一个在右边,或者一个在下面,一个在上面...分别x,y排序,然后扫一遍,同时记录坐标最大最小值就算一下就OK




【代码】

//bzoj 4578
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 1e9+7
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=50005;
ll ans=1e18+7,tot;
int n,m,mx,mn;
struct mnmx
{
	int minx[mxn],miny[mxn],maxx[mxn],maxy[mxn];
}A,B;
struct node {int x,y;} a[mxn];
inline bool comp_x(node a,node b)
{
	if(a.x==b.x) return a.y<b.y;
	return a.x<b.x;
}
inline bool comp_y(node a,node b)
{
	if(a.y==b.y) return a.x<b.x;
	return a.y<b.y;
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
int main()
{
	int i,j;
	n=read();
	fo(i,1,n) a[i].x=read(),a[i].y=read();
	
	sort(a+1,a+n+1,comp_x);
	ll ox=a[n].x-a[1].x;
	fo(i,0,n+1) A.miny[i]=B.miny[i]=A.minx[i]=B.minx[i]=inf;
	fo(i,1,n) A.miny[i]=min(A.miny[i-1],a[i].y),A.maxy[i]=max(A.maxy[i-1],a[i].y);
	for(i=n;i>=1;i--) B.miny[i]=min(B.miny[i+1],a[i].y),B.maxy[i]=max(B.maxy[i+1],a[i].y);
	fo(i,1,n-1) ans=min(ans,(ll)(A.maxy[i]-A.miny[i])*(a[i].x-a[1].x)+(ll)(B.maxy[i+1]-B.miny[i+1])*(a[n].x-a[i+1].x));
	
	sort(a+1,a+n+1,comp_y);
	ll oy=a[n].y-a[1].y;
	fo(i,1,n) A.minx[i]=min(A.minx[i-1],a[i].x),A.maxx[i]=max(A.maxx[i-1],a[i].x);
	for(i=n;i>=1;i--) B.minx[i]=min(B.minx[i+1],a[i].x),B.maxx[i]=max(B.maxx[i+1],a[i].x);
	fo(i,1,n-1) ans=min(ans,(ll)(A.maxx[i]-A.minx[i])*(a[i].y-a[1].y)+(ll)(B.maxx[i+1]-B.minx[i+1])*(a[n].y-a[i+1].y));
	
//	printf("%lld\n",ans);
	printf("%lld\n",ox*oy-ans);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值