• 题面描述

    • 某人在山上种了\(N\leq 2*10^4​\)棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的思考,他决定用\(3​\)个\(L*L​\)的正方形塑料薄膜将小树遮起来。我们不妨将山建立一个平面直角坐标系,设第\(i​\)棵小树的坐标为\((x_i,y_i)​\),\(3​\)个\(L*L​\)的正方形的边要求平行与坐标轴,一个点如果在正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求\(L​\)最小值。
  • 输入格式
    • 第一行有一个正整数\(N\),表示有多少棵树。接下来有\(N\)行,第\(i+1\)行有\(2\)个整数\(x_i,y_i\),表示第\(i\)棵树的坐标,保证不会有\(2\)个树的坐标相同。
  • 输出格式
    • 一行,输出最小的\(L\)值。
  • 题解
    • 先对给定的坐标\((x_i,y_i)\),找到恰好覆盖这些坐标的一个大矩形。
    • 首先,这个大矩形的四个边上必然都存在一个点,故大矩形边上至少有\(4\)个点。根据 抽屉原理,\(4\)个点要被\(3\)个小矩形覆盖其中必然有\(2\)个点被同一个矩阵覆盖。也就意味着,这个大矩形的\(4\)个顶角中必然有一个顶角被一个小矩形覆盖。
    • 因此,我们可以先二分\(L\),对于每个\(L\),枚举其中第一个小矩形覆盖哪一个大矩形的顶角。把问题划归为一个更小的子问题(用两个小矩形覆盖一些点)。再利用同样的技巧,对第二个小矩形(边长同样为\(L\))枚举它覆盖剩余点围成的大矩形的那个顶角。
    • 最后对于剩下的点判定能被第三个\(L*L\)的小矩形完全覆盖
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=2e4+5;
struct rec{
int x,y;
} a[MAXN],b[5],c[5];
int n,up,dn,rig,lef;
bool use[MAXN],res[MAXN];
bool solve(int L){
up=dn=rig=lef=0;
for (int i=1;i<=n;i++){
if (use[i]) continue;
if (a[up].y<a[i].y||up==0) up=i;
if (a[dn].y>a[i].y||dn==0) dn=i;
if (a[rig].x<a[i].x||rig==0) rig=i;
if (a[lef].x>a[i].x||lef==0) lef=i;
}
if (up==0) return 1;
c[1]=(rec){a[lef].x,a[up].y};
c[2]=(rec){a[rig].x,a[up].y};
c[3]=(rec){a[rig].x,a[dn].y};
c[4]=(rec){a[lef].x,a[dn].y};
// cout<<"sol2:"<<endl;
// for (int i=1;i<=4;i++){
// cout<<" "<<i<<" "<<c[i].x<<" "<<c[i].y<<endl;
// }
bool flag=0;
for (int i=1;i<=4;i++){
// cout<<" tp2: "<<i<<endl;
int dx=1,dy=1;
if (i==1) dy=-1;
if (i==2) dx=-1,dy=-1;
if (i==3) dx=-1;
int x=c[i].x,y=c[i].y;
int nx=x+dx*L,ny=y+dy*L;
int xl=min(x,nx),xr=max(x,nx);
int yl=min(y,ny),yr=max(y,ny);
for (int j=1;j<=n;j++) res[j]=use[j];
// cout<<" cvr2: ";
for (int j=1;j<=n;j++){
if (res[j]) continue;
if (a[j].x<xl||a[j].x>xr) continue;
if (a[j].y<yl||a[j].y>yr) continue;
res[j]=1;// cout<<j<<" ";
}
// cout<<endl;
up=dn=lef=rig=0;
for (int j=1;j<=n;j++){
if (res[j]) continue;
if (a[up].y<a[j].y||up==0) up=j;
if (a[dn].y>a[j].y||dn==0) dn=j;
if (a[lef].x>a[j].x||lef==0) lef=j;
if (a[rig].x<a[j].x||rig==0) rig=j;
}
if (up==0) return 1;
int tmp=max(a[up].y-a[dn].y,a[rig].x-a[lef].x);
// cout<<" endLen: "<<tmp<<endl;
flag|=(tmp<=L);
}
return flag;
}
bool check(int L){
bool flag=0;
for (int i=1;i<=4;i++){
// cout<<L<<" tp: "<<i<<endl;
int dx=1,dy=1;
if (i==1) dy=-1;
if (i==2) dx=-1,dy=-1;
if (i==3) dx=-1;
int x=b[i].x,y=b[i].y;
int nx=x+dx*L,ny=y+dy*L;
int xl=min(x,nx),xr=max(x,nx);
int yl=min(y,ny),yr=max(y,ny);
// cout<<"cvr: ";
for (int j=1;j<=n;j++){
use[j]=0;
if (a[j].x<xl||a[j].x>xr) continue;
if (a[j].y<yl||a[j].y>yr) continue;
use[j]=1;// cout<<j<<" ";
}
// cout<<endl;
// cout<<"flg: "<<solve(L)<<endl;
flag|=solve(L);
}
return flag;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
for (int i=1;i<=n;i++){
if (a[up].y<a[i].y||up==0) up=i;
if (a[dn].y>a[i].y||dn==0) dn=i;
if (a[rig].x<a[i].x||rig==0) rig=i;
if (a[lef].x>a[i].x||lef==0) lef=i;
}
b[1]=(rec){a[lef].x,a[up].y};
b[2]=(rec){a[rig].x,a[up].y};
b[3]=(rec){a[rig].x,a[dn].y};
b[4]=(rec){a[lef].x,a[dn].y};
// for (int i=1;i<=4;i++){
// cout<<i<<" "<<b[i].x<<" "<<b[i].y<<endl;
// }
// cout<<endl;
int l=0,r=max(a[up].y-a[dn].y,a[rig].x-a[lef].x),mid;
while (l+1<r){
mid=(l+r)>>1;
if (check(mid)) r=mid;
else l=mid;
}
printf("%d\n",r);
return 0;
}

天助自助者

随机推荐

  1. js选择文件夹路径

    该方法只支持IE. 语法:strDir=Shell.BrowseForFolder(Hwnd,Title,Options,[RootFolder])参数:Hwnd:包含对话框的窗体句柄(handle) ...

  2. jQuery 演变史

    一.说明 最近我读完了 jQuery 官方的博客仓库,目的是为了梳理清楚 jQuery API 接口的演变过程.从而明确知道在对应版本下使用正确.合适的 API,以下便是我的总结笔记. jQuery ...

  3. web大文件上传控件-监控fd_create流程-Xproer.HttpUploader6

      监控fd_create流程 1.打开ie,f12 2.启动网络监控 点击开始捕获 上传文件夹,然后查看监控 将监控信息转到详细视图

  4. 第06章-渲染Web视图

    1. 理解视图解析 将控制器中请求处理的逻辑和视图中的渲染实现解耦是Spring MVC的一个重要特性.如果控制器中的方法直接负责产生HTML的话,就很难在不影响请求处理逻辑的前提下,维护和更新视图. ...

  5. 编写高质量代码改善C#程序的157个建议——建议1:正确操作字符串

    最近拜读了陆敏技老师的<编写高质量代码改善C#程序的157个建议>,感觉不错,决定把笔记整理一遍. 建议1: 正确操作字符串 字符串应该是所有编程语言中使用最频繁的一种基础数据类型.如果使 ...

  6. 如何快速搭建基于python+appium的自动化测试环境

    首先申明本文是基本于Python与Android来快速搭建Appium自动化测试环境: 主要分为以下几个步骤: 前提条件: 1)安装与配置python环境,打开 Python官网,找到“Downloa ...

  7. vba实现excel多表合并

    Excel多表合并之vba实现 需求 保留列名,复制每一个excel里的数据,合并到一个excel 操作步骤 将要合并的文件放在同一文件夹下,复制过来就好(ps:最好不要直接操作原数据文件,避免操作失 ...

  8. go的同步模型

    首先来看一段代码,这是The Go Memory Model一文中的一个例子   var a, b int   func f() {     a = 1     b = 2 } func g() { ...

  9. Spring学习----自动装配@Resource、@Autowired、@Qualifier

    直接看下面的代码即可明白: applicationContext.xml里面添加个bean: <!--注解的注入 --> <bean id="student3" ...

  10. C# 抽象(4)

    抽象类和普通类有区别嘛?在继承的时候,还是只能继承一次父类嘛? 答案: 抽象类除了在抽象方法和属性上面不能实现具体的代码之外和普通类没有区别.依旧符合类的基本特征.所以在继承的时候抽象类也是属于基类, ...