本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
【Codeforces】Codeforces Round #330 (Div. 1) C. Edo and Magnets | 暴力、贪心
题目链接
题目
题目大意
在二维平面内有 个与坐标轴平行的整点矩形,第 个矩形描述为 ,表示第 个矩形左下角的坐标是 和右下角的坐标是 。保证 均为正整数。
删除其中不超过 个矩形后,构造矩形 ,使得未被删除的矩形的几何中心均在 的内部或者在 上。且矩形 的边应该与坐标轴平行,它的四个顶点均应该为整点。
输出合法矩形 面积的最小值。
思路
我们在点集 中构造矩形 ,点集中最上最下最左最右的点都在 的边上,我们可以唯一构造矩形 。
又因为删除的点的数量很少,我们可以先对所有的点对 坐标和 坐标分别排序并存储,枚举我们自上而下删除了 个点,自下而上删除了 个点,自左向右删除了 个点,显然删除更多的点答案不会变差,所以自右向左删除了 个点。
我们可以轻松找到剩余的点集,并构造紧紧包含剩余点集的矩形的面积(横纵坐标极值分别作差后相乘即可),更新答案即可。注意这里我们认为点和线不能被称为矩形,所以我们计算面积时两边的边长应该与 取 。
为了方便编码提升精度我一开始将坐标同乘了 2。
代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct asdf{
long long x,y;
int id;
}a[100005],b[100005];
int n,k,m;
int cmpx(asdf a,asdf b){return a.x<b.x;}
int cmpy(asdf a,asdf b){return a.y<b.y;}
int v[100005];
long long solve(int u,int d,int l,int r)
{
for (int i=1;i<=k;++i) v[a[i].id]=v[b[i].id]=v[a[n-i+1].id]=v[b[n-i+1].id]=0;
int ix=1,iy=1,ax=n,ay=n;
while (u) u-=(v[a[ix].id]==0),v[a[ix++].id]=1;
while (d) d-=(v[a[ax].id]==0),v[a[ax--].id]=1;
while (l) l-=(v[b[iy].id]==0),v[b[iy++].id]=1;
while (r) r-=(v[b[ay].id]==0),v[b[ay--].id]=1;
while (v[a[ix].id]) ix++;
while (v[a[ax].id]) ax--;
while (v[b[iy].id]) iy++;
while (v[b[ay].id]) ay--;
return max(1ll,(a[ax].x-a[ix].x+1)/2)*max(1ll,(b[ay].y-b[iy].y+1)/2);
}
int main()
{
scanf("%d%d",&n,&k);
int x[4];
for (int i=1;i<=n;++i)
{
for (int j=0;j<4;++j) scanf("%d",&x[j]);
a[i].x=x[0]+x[2];
a[i].y=x[1]+x[3];
a[i].id=i;
b[i]=a[i];
}
sort(a+1,a+1+n,cmpx);
sort(b+1,b+1+n,cmpy);
long long ans=1e18+100;
for (int u=0;u<=k;++u)
for (int d=0;u+d<=k;++d)
for (int l=0;u+d+l<=k;++l)
ans=min(ans,solve(u,d,l,k-u-d-l));
printf("%lld\n",ans);
return 0;
}