ACWing123(二维坐标离散化或双指针)
做法1:双指针
AC代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 510;
pair<int,int> a[N];
int c, n;
bool check(int now)
{
for(int i = 1; i <= n; i ++ ) //确定最大左右边界 i, j
{
int j = 0;
while(j <= n && a[j].first - a[i].first <= now) j ++;
/*
在点集 [i,n] 里面查找以与左边界 i 距离小于 now 的点
可以会问如果 j 在 i 的左侧怎么办,因为这里显然有j < i 的情况,但其实是不需要判断的
因为区间长度 j - i + 1是可以忽略掉在 i 左侧的 j 的情况
(1)到最后 j 都在 i 的左侧,那么j - i + 1 <= 0 恒成立,返回flase
(2)一部分 j 在 i 左侧,一部分 j 在 i 右侧,j - i + 1 不包含 j 在 i 左侧的 j
可能会问直接在i里面加上 j > i 的判断不就好了?其实这样是不好的,因为不方便统计 j 的个数
*/
j --; //因为 j = 0处 a[j] 没有定义,但 a[j] 又明显符合,所以 j--,
if(j - i + 1 < c)
return false;
/*
这里合适的话不能返回true,因为这里只是确定了X轴的区间是满足的,还没有确定Y轴
即如果Y轴所需要的区间边长大于我们check的边长now,也是不符合的
但如果X轴的区间边长都不满足,一定不满足,直接返回false
*/
for(int k = i; k <= j; k ++ ) //检查Y轴,枚举每一个点的Y轴上下界
{
int l = a[k].second, r = a[k].second + now, ans = 0;//以该点Y轴的范围作为上下边界
for(int u = i; u <= j; u ++ ) //查找符合的点
if(a[u].second >= l && a[u].second <= r)
ans++;
if(ans >= c)
return true;
}
}
return false;
}
int main()
{
cin >> c >> n;
for(int i = 1; i <= n; i ++ )
{
int x, y;
cin >> x >> y;
a[i] = {x, y};
}
sort(a + 1, a + n + 1); //不排序 check 函数毫无意义
//默认排序:first从到大排序,first相同时second从小到大排序
int l = 1, r = 10000;
while(l < r)
{
int mid = l + r >> 1;
if(check(mid - 1))//因为每一个草占据一个矩形,所以求得的半径要大1,遍历的时候就要减1
r = mid;
else
l = mid + 1;
}
cout << l << endl;
return 0;
}