比赛
题目
题意:
有一些房子和两个点。每次查询给出以两个点为圆心的圆的半径,在一个圆内的房子发一套防化服,所以相交部分的房子有两套,不在圆内的没有。将相交部分的房子多余的防化服发给没有的房子后,求还有多少房子没有防化服。
题解:
因为最后有防化服的房子只由一套防化服,所以就是求发出了多少套防化服。将每个房子到两个点的距离预处理出来,那么对于给定的半径二分就知道有多少房子在圆内。
//Time:238ms //Memory:0KB //Length:1312B #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define MAXN 200010 #define MAXM 100010 #define EPS 1e-8 int x[MAXN],y[MAXN]; double nee[2][MAXN]; int top[2]; double cal(int a,int b) { return sqrt(1.0*(x[a]-x[b])*(x[a]-x[b])+1.0*(y[a]-y[b])*(y[a]-y[b])); } int bs(double arr[],int r,double key) { int l=0,mid; while(l<r) { mid=(l+r+1)/2; if(arr[mid]>key+EPS) r=mid-1; else l=mid; } return l; } int main() { //freopen("/home/moor/Code/input","r",stdin); int n,q,cnt=0; while(scanf("%d",&n)==1&&n) { printf("Case %d:\n",++cnt); for(int i=0;i<n;++i) scanf("%d%d",&x[i],&y[i]); scanf("%d%d",&x[n+1],&y[n+1]); scanf("%d%d",&x[n+2],&y[n+2]); for(int i=0;i<n;++i) nee[0][i]=cal(i,n+1), nee[1][i]=cal(i,n+2); nee[0][n]=0; nee[1][n]=0; sort(nee[0],nee[0]+n+1); sort(nee[1],nee[1]+n+1); scanf("%d",&q); for(int i=0;i<q;++i) { int r1,r2,n1,n2; scanf("%d%d",&r1,&r2); n1=bs(nee[0],n+1,r1); n2=bs(nee[1],n+1,r2); printf("%d\n",max(n-n1-n2,0)); } } return 0; }