队内赛做的一道题..第一个关键是题意的把握...意思是每个nuclear plant可以在其R范围内发放保护装备..如果一个点被一个nuclear plant覆盖就拿一个装备..如果被两个覆盖拿两个装备..没有被任何的覆盖..领不到装备...拿了两个装备的把多余装备给没有装备的..问最终有多少人依然是没有装备的...
由于两个nuclear plant以及所有的点都是固定的..所以可以先把所有点到plant A 的距离和plant B的距离算出来..排序分别存在两个数组中...对于当前询问R1,R2..可用二分查找快速得出有多少点被A覆盖..多少点被B覆盖...相加记为sum....那么总人数N-sum既是最后也拿不到装备的人数..注意..有可能N-sum<0..所以输出时max(0,N-sum)...
Program:
//https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=585&page=show_problem&problem=4155 #include<iostream> #include<stdio.h> #include<string.h> #include<cmath> #include<algorithm> #include<map> #include<set> #include<queue> #define ll long long #define oo 1000000001 #define MAXN 200002 using namespace std; struct node1 { int x,y; }point[MAXN],a,b; int d1[MAXN],d2[MAXN],n; int main() { // freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); int i,q,R1,R2,l,r,mid,sum,t=0; while (~scanf("%d",&n)) { if (!n) break; printf("Case %d:\n",++t); for (i=1;i<=n;i++) scanf("%d%d",&point[i].x,&point[i].y); scanf("%d%d%d%d%d",&a.x,&a.y,&b.x,&b.y,&q); for (i=1;i<=n;i++) { d1[i]=(point[i].x-a.x)*(point[i].x-a.x)+(point[i].y-a.y)*(point[i].y-a.y); d2[i]=(point[i].x-b.x)*(point[i].x-b.x)+(point[i].y-b.y)*(point[i].y-b.y); } sort(d1+1,d1+1+n); sort(d2+1,d2+1+n); while (q--) { scanf("%d%d",&R1,&R2); R1*=R1; R2*=R2; l=0; r=n+1; while (r-l>1) { mid=(r+l)/2; if (d1[mid]<=R1) l=mid; else r=mid; } sum=l; l=0; r=n+1; while (r-l>1) { mid=(r+l)/2; if (d2[mid]<=R2) l=mid; else r=mid; } sum+=l; printf("%d\n",max(n-sum,0)); } } return 0; }