您的位置:首页 > 其它

1199: [HNOI2005]汤姆的游戏 - BZOJ

2014-03-11 17:45 260 查看
Description

汤姆是个好动的孩子,今天他突然对圆规和直尺来了兴趣。于是他开始在一张很大很大的白纸上画很多很多的矩形和圆。画着画着,一不小心将他的爆米花弄撒了,于是白纸上就多了好多好多的爆米花。汤姆发现爆米花在白纸上看起来就像一个个点,有些点落在矩形或圆内部,而有些则在外面。于是汤姆开始数每个点在多少个矩形或圆内部。毕竟汤姆还只是个孩子,而且点、矩形和圆又非常多。所以汤姆数了好一会都数不清,于是就向聪明的你求助了。你的任务是:在给定平面上N个图形(矩形或圆)以及M个点后,请你求出每个点在多少个矩形或圆内部(这里假设矩形的边都平行于坐标轴)。
Input

第一行为两个正整数N和M,其中N表示有多少个图形(矩形或圆),M表示有多少个点。接下来的N行是对每个图形的描述,具体来说,第i+1行表示第i个图形。先是一个字母,若该字母为“r”,则表示该图形是一个矩形,这时后面将有4个实数x1,y1,x2,y2,表示该矩形的一对对角顶点的坐标分别为(x1,y1)和(x2,y2);若该字母为“c”,则表示该图形是一个圆,这时后面将有3个实数x,y,r,表示该圆以(x,y)为圆心并以r为半径。最后M行是对每个点的描述,其中每行将有两个实数x,y,表示一个坐标为(x,y)的点。
Output

包含M行,每行是一个整数,其中第i行的整数表示第i个点在多少个图形内部(当某点在一个图形的边界上时,我们认为该点不在这个图形的内部)。
Sample Input

3 4

r 1.015 0.750 5.000 4.000

c 6.000 5.000 2.020

r 6.500 7.200 7.800 9.200

3.500 2.500

4.995 3.990

2.300 8.150

6.900 8.000

Sample Output

1

2

0

1

好吧,写了很久,最后发现数组越界了(第20组n是20万,第18组就是25万,我只看了第20组数据.....谁叫他题目不写清楚,只能自己下数据了)

看了网上的C++程序,知道做法了

先将点按x坐标排序,再二分出有效区间即x坐标在矩形两个横坐标之间,或者在(x-r,x+r)之间的点,然后暴力是否被覆盖,统计答案

因为最开始那个问题,我还到处问人,去贴吧问,最后在我写完C++程序(照着网上的代码写)的时候发现n最大有25万,顿时崩溃了,改完就过了

#include<cstdio>
#include<algorithm>
using namespace std;

typedef double ld;

const int maxn=250010;
const int maxm=10010;
const ld eps=1e-7;

int n,m,ans[maxm];

struct REC
{
ld lx,ly,rx,ry;
}rec[maxn];
int numr;

struct CIR
{
ld x,y,r;
}cir[maxn];
int numc;

struct point
{
ld x,y;
int k;
}d[maxm];

int operator < (const point & a,const point & b)
{
return a.x<b.x;
}

int main()
{
int i,j;
scanf("%d%d",&n,&m);
char s;
for(i=1;i<=n;++i)
{
scanf("%s",&s);
if(s=='r')
{
++numr;
scanf("%lf%lf%lf%lf",&rec[numr].lx,&rec[numr].ly,&rec[numr].rx,&rec[numr].ry);
if(rec[numr].lx>rec[numr].rx)
swap(rec[numr].lx,rec[numr].rx);
if(rec[numr].ly>rec[numr].ry)
swap(rec[numr].ly,rec[numr].ry);
}
else
{
++numc;
scanf("%lf%lf%lf",&cir[numc].x,&cir[numc].y,&cir[numc].r);
}
}
for(i=1;i<=m;++i)
{
scanf("%lf%lf",&d[i].x,&d[i].y);
d[i].k=i;
}
sort(d+1,d+m+1);
int left,right,ll,rr,mid;
for(i=1;i<=numr;++i)
{
left=1,right=m;
while(left<right)
{
mid=(left+right)/2;
if(d[mid].x>rec[i].lx)right=mid;
else left=mid+1;
}
ll=left;
left=1;right=m;
while(left<right)
{
mid=(left+right+1)/2;
if(d[mid].x<rec[i].rx)left=mid;
else right=mid-1;
}
rr=right;
for(j=ll;j<=rr;++j)
if((d[j].x>rec[i].lx+eps)&(rec[i].rx>d[j].x+eps)&(d[j].y>rec[i].ly+eps)&(rec[i].ry>d[j].y+eps))
++ans[d[j].k];
}
for(i=1;i<=numc;++i)
{
left=1;right=m;
while(left<right)
{
mid=(left+right)/2;
if(d[mid].x>cir[i].x-cir[i].r)right=mid;
else left=mid+1;
}
ll=left;
left=1;right=m;
while(left<right)
{
mid=(left+right+1)/2;
if(cir[i].x+cir[i].r>d[mid].x)left=mid;
else right=mid-1;
}
rr=right;
for(j=ll;j<=rr;++j)
if(cir[i].r*cir[i].r>(d[j].x-cir[i].x)*(d[j].x-cir[i].x)+(d[j].y-cir[i].y)*(d[j].y-cir[i].y))
++ans[d[j].k];
}
for(i=1;i<=m;++i)
printf("%d\n",ans[i]);
return 0;
}


C++代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: