题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4155
题目大意:寻找两个圆的交集部分的点的个数c1,之后再寻找圆外面的点的个数c2。如果c2<c1则输出0,否则输出c2-c1
解题思路:
这个题目如果纯粹的暴力肯定是超时(别尝试了,我已经暴了N遍了,还是TLE)。关键还是优化算法,利用容斥原理+二分+排序
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<string> #include<stack> #include<queue> #include<vector> #include<algorithm> #include<iostream> #define maxn 200000+10 using namespace std; #ifdef __int64 typedef __int64 LL; #else typedef long long LL; #endif int v[maxn][2]; double d1[maxn],d2[maxn];//保存每个点到两个圆的圆心的距离 int bs(double s[],int l,int h,int v)//二分查找,找出在圆内有多少个点 { while(l<h) { int m=(l+h)>>1; if(s[m]<=v) { l=m+1; } else { h=m; } } return l; } int main() { int t,ncase=1; while(scanf("%d",&t)&&t) { printf("Case %d:\n",ncase++); for(int i=0;i<t;i++) { scanf("%d%d",&v[i][0],&v[i][1]); } int x1,y1,x2,y2,q; scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&q); for(int i=0;i<t;i++) { d1[i]=(double)sqrt((v[i][0]-x1)*(v[i][0]-x1)+(v[i][1]-y1)*(v[i][1]-y1)); d2[i]=(double)sqrt((v[i][0]-x2)*(v[i][0]-x2)+(v[i][1]-y2)*(v[i][1]-y2)); } sort(d1,d1+t); sort(d2,d2+t); int c1,c2; while(q--) { double a,b; scanf("%lf%lf",&a,&b); c1=bs(d1,0,t-1,a);//printf("c1=%d\n",c1); c2=bs(d2,0,t-1,b);//printf("c2=%d\n",c2); if(t-c1-c2<=0) printf("0\n"); else printf("%d\n",t-c1-c2); } } return 0; }