UVALive 6144 Radiation 二分

        此题是2012年区域赛泰国一个赛区的题目,可能是东南亚赛区比较水,做完前面3道签到题之后,其实发现这个题也是一个大水题,只要能够稍微yy一下就可以了,毕竟东南亚,这个题也很考英语,具体意思为给你n个点的坐标,然后再给你两个圆的坐标圆心,并且给q个询问,每次给你两个圆的半径r1和r2,问你在这个图中没有被两个圆包住的点减去同时被2个圆包住的点的数量有多少???如果小于0,输出0。

这个题目做法其实不难,具体就是图的转化,可以想一下,未被包住的点的数量减去同时都被包住的点的数量等于图中所有的点n减去两个圆分别包含的点的数量(此时同时被包住的点的数量会算两遍),所以此题就简单多了,先求出所有点到圆的距离,再对距离进行排序,然后对每次给定的半径,直接二分寻找存在多少个点被包到圆里面,直接输出n减去两次求的的数量之和即可AC。。。PS:由于此题距离如果直接使用,可能会有一定的精度误差很难去处理,我就直接用距离平方去计算,从而避免了精度问题,具体代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const double eps=1e-6;
struct st
{
    int x,y;
}p[200005];
int cal(st p,st c)
{
    return (p.x-c.x)*(p.x-c.x)+(p.y-c.y)*(p.y-c.y);
}
int cd1[200005],cd2[200005];
int cmp(const void *a,const void *b)
{
    return *(int*)a-*(int*)b;
}
int main()
{
  //  freopen("in.txt","r",stdin);
    int n,ti=1;
    while(cin>>n&&n!=0)
    {
        for(int i=0;i<n;i++)
            scanf("%d%d",&p[i].x,&p[i].y);
        st c1,c2;
        int m;
        scanf("%d%d%d%d%d",&c1.x,&c1.y,&c2.x,&c2.y,&m);
        for(int i=0;i<n;i++)
        {
            cd1[i]=cal(p[i],c1);
            cd2[i]=cal(p[i],c2);
        }
        qsort(cd1,n,sizeof(cd1[0]),cmp);
        qsort(cd2,n,sizeof(cd2[0]),cmp);
        printf("Case %d:\n",ti);
        ti++;
        for(int i=0;i<m;i++)
        {
            int r1,r2;
            scanf("%d%d",&r1,&r2);
            int ans1=upper_bound(cd1,cd1+n,r1*r1)-cd1,ans2=upper_bound(cd2,cd2+n,r2*r2)-cd2;
            if(n-ans1-ans2<=0)
                cout<<0<<endl;
            else
                cout<<n-(ans1+ans2)<<endl;
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值