【CERC2015】【BZOJ4434】Ice Igloos

Description

一个坐落在北极冰冻湖面上的渔村因全球变暖而面临危险——湖面开始破碎。村庄内有n座球形冰屋,每座冰屋在湖面上占据了一块圆形区域。
一座冰屋可以视为平面座标系中的一个圆:其圆心座标为整数,其半径为小于1的一位浮点数。给出冰面断裂的座标,这些村民希望知道每次断裂会有多少个冰屋受到影响。
形式上,给出q个询问,每个询问包括一条由两个端点确定的线段,查询每条线段贯穿的冰屋数。如果线段与圆的内部有至少一个交点,则线段贯穿了这座冰屋。

Input

第一行包括一个整数n(1<=n<=100 000)——冰屋数。
接下来的n行每行包括三个数x,y和r——冰屋的座标和半径。x和y为整数且1<=x,y<=500。r是一位浮点数且0

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define eps 1e-6
#define SIZE 510
#define MAXN 100010
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,q;
double r[SIZE][SIZE];
double A,B,C,k,b;
inline void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
inline void fin(double &x)
{
    char ch=getchar();x=0;double f=1;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
    while (!GET)    ch=getchar();
    while (GET) f*=0.1,x=x+f*(ch-'0'),ch=getchar();
}
inline void init(int x1,int y1,int x2,int y2)
{
    A=(y2-y1);B=(x1-x2);
    double len=sqrt(A*A+B*B);
    A/=len;B/=len;C=-(A*x1+B*y1);
    k=(double)(y2-y1)/(x2-x1);b=y1-k*x1;
}
inline double f(int x)  {   return k*x+b;   }
inline double dis(int x,int y)  {   return fabs(A*x+B*y+C); }
inline int calc(int x,int y1,int y2)
{
    int ret=0;
    for (int i=y1;i<=y2;i++) ret+=(r[x][i]>0.0&&dis(x,i)<=r[x][i]);
    return ret;
}
int main()
{
    in(n);int x,y,x1,y1,x2,y2;double z;
    for (int i=1;i<=n;i++)   in(x),in(y),fin(z),r[x][y]=z;
    for (in(q);q;q--)
    {
        in(x1);in(y1);in(x2);in(y2);int ans=0;
        if (x1>x2||(x1==x2&&y1>y2))   swap(x1,x2),swap(y1,y2);
        if (x1==x2) for (int i=y1;i<=y2;i++) ans+=(r[x1][i]>0.0);
        else    if (y1==y2) for (int i=x1;i<=x2;i++) ans+=(r[i][y1]>0.0);
        else
        {
            init(x1,y1,x2,y2);
            if (y2>y1)
            {
                int ty1=y1,ty2=ceil(f(x1+1)-eps);
                ans+=calc(x1,ty1,ty2);
                for (int i=x1+1;i<x2;i++)
                {
                    int tmp=ty2;ty2=ceil(f(i+1)-eps);
                    ans+=calc(i,ty1,ty2);ty1=tmp-1;
                }
                ans+=calc(x2,ty1,ty2);
            }
            else
            {
                int ty1=y1,ty2=floor(f(x1+1)+eps);
                ans+=calc(x1,ty2,ty1);
                for (int i=x1+1;i<x2;i++)
                {
                    int tmp=ty2;ty2=floor(f(i+1)+eps);
                    ans+=calc(i,ty2,ty1);ty1=tmp+1;
                }
                ans+=calc(x2,ty2,ty1);
            }
        }
        printf("%d\n",ans);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值