https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3001
二分枚举+贪心操作
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
int k,n,s,d;
struct Node{
int l,r,x,y;
void init(int now)
{
int ans=sqrt((long long)(d)*(long long)(d)-(long long)(now+y)*(long long)(now+y));
// printf("%d sqrt%d \n",d*d-(now-y)*(now-y),ans);
l=x-ans;
r=x+ans;
}
}data[20010];
bool cmp(Node a,Node b)
{
return a.r<=b.r;
}
bool check (int now)
{
for (int i=0;i<n;i++)
{
data[i].init(now);
}
sort(data,data+n,cmp);
int mlr=data[0].r;
int cnt=1;
for (int i=0;i<n;i++)
{
if(data[i].l<=mlr)
{
continue;
}
else {
cnt++;
mlr=data[i].r;
}
}
if(cnt<=s) return 1;
else return 0;
}
int main ()
{
int T,cas=0;
//freopen ("data.in","r",stdin);
//freopen ("data.out","w",stdout);
scanf("%d",&T);
while (T--)
{
int low=1,high=1e9+10;
scanf("%d%d%d%d",&k,&n,&s,&d);
for (int i=0;i<n;i++)
{
scanf("%d%d",&data[i].x,&data[i].y);
data[i].y-=k;
high=min(high,d-(data[i].y));
}
int ans=-1;
int m;
while (high>=low)
{
m=(high+low)/2;
if(check(m))
{
ans=m;
low=m+1;
}
else {
high=m-1;
}
}
if(ans==-1) printf("Case %d: IMPOSSIBLE\n",++cas);
else
printf("Case %d: %d\n",++cas,ans);
}
return 0;
}