1199: [HNOI2005]汤姆的游戏 - BZOJ
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万,顿时崩溃了,改完就过了
const
eps=1e-7;
type
extended=double;
var
cx,cr,cy:array[..]of extended;
lx,ly,rx,ry:array[..]of extended;
ans,k:array[..]of longint;
x,y:array[..]of extended;
n,m,numr,numc:longint; procedure swap(var x,y:extended);
var
t:extended;
begin
t:=x;x:=y;y:=t;
end; procedure sort(l,r:longint);
var
i,j,t:longint;
z:extended;
begin
i:=l;
j:=r;
z:=x[(l+r)>>];
repeat
while z>x[i]+eps do
inc(i);
while x[j]>z+eps do
dec(j);
if i<=j then
begin
swap(x[i],x[j]);
swap(y[i],y[j]);
t:=k[i];k[i]:=k[j];k[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if i<r then sort(i,r);
if j>l then sort(l,j);
end; procedure init;
var
i:longint;
s:char;
begin
read(n,m);
for i:= to n do
begin
read(s);
while (s<>'r')and(s<>'c') do
read(s);
if s='r' then
begin
inc(numr);
read(lx[numr],ly[numr],rx[numr],ry[numr]);
if lx[numr]>rx[numr] then swap(lx[numr],rx[numr]);
if ly[numr]>ry[numr] then swap(ly[numr],ry[numr]);
end
else
begin
inc(numc);
read(cx[numc],cy[numc],cr[numc]);
end;
end;
for i:= to m do
read(x[i],y[i]);
for i:= to m do
k[i]:=i;
sort(,m);
end; procedure work;
var
i,j,ll,rr,left,right,mid:longint;
begin
for i:= to numc do
begin
left:=;right:=m;
while left<right do
begin
mid:=(left+right)>>;
if x[mid]>cx[i]-cr[i] then right:=mid
else left:=mid+;
end;
ll:=left;
left:=;right:=m;
while left<right do
begin
mid:=(left+right+)>>;
if cx[i]+cr[i]>x[mid] then left:=mid
else right:=mid-;
end;
rr:=right;
for j:=ll to rr do
if sqr(cr[i])-eps>sqr(x[j]-cx[i])+sqr(y[j]-cy[i]) then inc(ans[k[j]]);
end;
for i:= to numr do
begin
left:=;right:=m;
while left<right do
begin
mid:=(left+right)>>;
if x[mid]>lx[i] then right:=mid
else left:=mid+;
end;
ll:=left;
left:=;right:=m;
while left<right do
begin
mid:=(left+right+)>>;
if rx[i]>x[mid] then left:=mid
else right:=mid-;
end;
rr:=right;
for j:=ll to rr do
if (y[j]>ly[i]+eps)and(ry[i]>y[j]+eps)and(x[j]>lx[i]+eps)and(rx[i]>x[j]+eps) then inc(ans[k[j]]);
end;
for i:= to m do
writeln(ans[i]);
end; begin
init;
work;
end.
pascal代码
#include<cstdio>
#include<algorithm>
using namespace std; typedef double ld; const int maxn=;
const int maxm=;
const ld eps=1e-; 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=;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=;i<=m;++i)
{
scanf("%lf%lf",&d[i].x,&d[i].y);
d[i].k=i;
}
sort(d+,d+m+);
int left,right,ll,rr,mid;
for(i=;i<=numr;++i)
{
left=,right=m;
while(left<right)
{
mid=(left+right)/;
if(d[mid].x>rec[i].lx)right=mid;
else left=mid+;
}
ll=left;
left=;right=m;
while(left<right)
{
mid=(left+right+)/;
if(d[mid].x<rec[i].rx)left=mid;
else right=mid-;
}
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=;i<=numc;++i)
{
left=;right=m;
while(left<right)
{
mid=(left+right)/;
if(d[mid].x>cir[i].x-cir[i].r)right=mid;
else left=mid+;
}
ll=left;
left=;right=m;
while(left<right)
{
mid=(left+right+)/;
if(cir[i].x+cir[i].r>d[mid].x)left=mid;
else right=mid-;
}
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=;i<=m;++i)
printf("%d\n",ans[i]);
return ;
}
C++代码
1199: [HNOI2005]汤姆的游戏 - BZOJ的更多相关文章
- BZOJ 1199: [HNOI2005]汤姆的游戏 计算几何暴力
1199: [HNOI2005]汤姆的游戏 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...
- 洛谷 P2313 [HNOI2005]汤姆的游戏 题解
P2313 [HNOI2005]汤姆的游戏 题目描述 汤姆是个好动的孩子,今天他突然对圆规和直尺来了兴趣.于是他开始在一张很大很大的白纸上画很多很多的矩形和圆.画着画着,一不小心将他的爆米花弄撒了,于 ...
- 几何【P2313】 [HNOI2005]汤姆的游戏
顾z 你没有发现两个字里的blog都不一样嘛 qwq 题目描述--->p2313 [HNOI]汤姆的游戏 分析 说不上是分析. 数据范围给出来,这题明显暴力啊emmm. 个人认为的坑点. 这题不 ...
- P2313 [HNOI2005]汤姆的游戏
题目描述 汤姆是个好动的孩子,今天他突然对圆规和直尺来了兴趣.于是他开始在一张很大很大的白纸上画很多很多的矩形和圆.画着画着,一不小心将他的爆米花弄撒了,于是白纸上就多了好多好多的爆米花.汤姆发现爆米 ...
- bzoj千题计划176:bzoj1199: [HNOI2005]汤姆的游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=1199 求出圆x的范围 把要判断的点按x从小到大排序 枚举图形 二分出x满足这个图形的一段区间 枚举这 ...
- [HNOI2005]汤姆的游戏
嘟嘟嘟 直接O(n ^ 2)暴力判断就行了. 对于圆,判断该点和圆心的距离是否小于半径. 然而为啥我这么写编译不过: scanf("%lf%lf%lf%lf", &a[++ ...
- 汤姆大叔 javascript 系列 第20课 最后的5到javascript题目
博客链接:http://www.cnblogs.com/TomXu/archive/2012/02/10/2342098.html 原题: 大叔注:这些题目也是来自出这5个题目的人,当然如果你能答对4 ...
- 你必须知道ASP.NET知识------关于动态注册httpmodule(对不起汤姆大叔)
一.关于动态注册的问题 很多人看过汤姆大叔的MVC之前的那点事儿系列(6):动态注册HttpModule ,其实汤姆大叔没有发现httpmodule动态注册的根本机制在哪里. 亦即:怎么动态注册?为什 ...
- 我读汤姆大叔的深入理解js(二)
继续汤姆大叔的js之旅. 揭秘命名函数表达式 函数表达式和函数声明 汤姆大叔在博客中引用ECMA规范:函数声明必须带有标识符,函数表达式可以省略.对于我来说这些概念的东西真是不所适从.还是大叔的实例带 ...
随机推荐
- XP下Winform背景透明问题
win 7上usercontrol控件背景色设置为透明,显示无异常.到XP上一看,变成Control颜色了,即常见的灰色.网上搜了一堆,没发现有用的.偶然看到XP上Label的背景色可以透明,于是用L ...
- 会话跟踪技术——Session
一.什么是Session Session从用户访问页面开始,到断开与网站连接为止,形成一个会话的生命周期.在会话期间,分配客户唯一的一个SessionID,用来标识当前用户,与其他用户进行区分. Se ...
- python学习day5--set、函数
1.set 无序,不重复序列 创建:与dict一样用{},区别在于dict内元素为键值对 se={"123","456,444"} print(type(se) ...
- sqlsever 关于索引
索引: 在sqlserver中,存储的单位最小是页,页是不可再分的B树:初衷是减少对磁盘的扫描次数,如果一个表或者索引没有使用B树(对于没有聚集索引的表是使用 Heap 堆进行存储的),那么查找一个数 ...
- Android之触屏事件
方法一: 新建"MyView"类 package onTouchEvent; import android.content.Context; import android.grap ...
- SQL Server内存数据写入磁盘方法比较
众所周知,SQLServer增删改数据最先都是在内存中进行的,这可以大大加快数据操作的速度: 当内存中的数据被修改了,而磁盘中的数据还没有被修改时,就产生了所谓的“脏页”,SQLServer是如何同步 ...
- Cocos2d-x开发实例介绍帧动画使用
下面我们通过一个实例介绍一下帧动画的使用,这个实例如下图所示,点击Go按钮开始播放动画,这时候播放按钮标题变为Stop,点击Stop按钮可以停止播放动画. 下面我们再看看具体的程序代码,首先看一下看H ...
- spring读取prperties配置文件(1)
博客地址http://www.cnblogs.com/shizhongtao/p/3438431.html 属性文件命名是*.properties,在java中,用类java.util.Propert ...
- DP入门数塔问题
在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少? 已经告诉你了,这 ...
- Ubuntu 截屏
一个图说明: 系统设置->键盘->快捷键->屏幕截图 里面可以查看及修改快捷键