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万,顿时崩溃了,改完就过了

 

  1 const
  2     eps=1e-7;
  3 type
  4     extended=double;
  5 var
  6     cx,cr,cy:array[0..250010]of extended;
  7     lx,ly,rx,ry:array[0..250010]of extended;
  8     ans,k:array[0..100010]of longint;
  9     x,y:array[0..100010]of extended;
 10     n,m,numr,numc:longint;
 11  
 12 procedure swap(var x,y:extended);
 13 var
 14     t:extended;
 15 begin
 16     t:=x;x:=y;y:=t;
 17 end;
 18  
 19 procedure sort(l,r:longint);
 20 var
 21     i,j,t:longint;
 22     z:extended;
 23 begin
 24     i:=l;
 25     j:=r;
 26     z:=x[(l+r)>>1];
 27     repeat
 28       while z>x[i]+eps do
 29         inc(i);
 30       while x[j]>z+eps do
 31         dec(j);
 32       if i<=j then
 33       begin
 34         swap(x[i],x[j]);
 35         swap(y[i],y[j]);
 36         t:=k[i];k[i]:=k[j];k[j]:=t;
 37         inc(i);
 38         dec(j);
 39       end;
 40     until i>j;
 41     if i<r then sort(i,r);
 42     if j>l then sort(l,j);
 43 end;
 44  
 45 procedure init;
 46 var
 47     i:longint;
 48     s:char;
 49 begin
 50     read(n,m);
 51     for i:=1 to n do
 52       begin
 53         read(s);
 54         while (s<>'r')and(s<>'c') do
 55           read(s);
 56         if s='r' then
 57           begin
 58             inc(numr);
 59             read(lx[numr],ly[numr],rx[numr],ry[numr]);
 60             if lx[numr]>rx[numr] then swap(lx[numr],rx[numr]);
 61             if ly[numr]>ry[numr] then swap(ly[numr],ry[numr]);
 62           end
 63         else
 64           begin
 65             inc(numc);
 66             read(cx[numc],cy[numc],cr[numc]);
 67           end;
 68       end;
 69     for i:=1 to m do
 70       read(x[i],y[i]);
 71     for i:=1 to m do
 72       k[i]:=i;
 73     sort(1,m);
 74 end;
 75  
 76 procedure work;
 77 var
 78     i,j,ll,rr,left,right,mid:longint;
 79 begin
 80     for i:=1 to numc do
 81       begin
 82         left:=1;right:=m;
 83         while left<right do
 84           begin
 85             mid:=(left+right)>>1;
 86             if x[mid]>cx[i]-cr[i] then right:=mid
 87             else left:=mid+1;
 88           end;
 89         ll:=left;
 90         left:=1;right:=m;
 91         while left<right do
 92           begin
 93             mid:=(left+right+1)>>1;
 94             if cx[i]+cr[i]>x[mid] then left:=mid
 95             else right:=mid-1;
 96           end;
 97         rr:=right;
 98         for j:=ll to rr do
 99           if sqr(cr[i])-eps>sqr(x[j]-cx[i])+sqr(y[j]-cy[i]) then inc(ans[k[j]]);
100       end;
101     for i:=1 to numr do
102       begin
103         left:=1;right:=m;
104         while left<right do
105           begin
106             mid:=(left+right)>>1;
107             if x[mid]>lx[i] then right:=mid
108             else left:=mid+1;
109           end;
110         ll:=left;
111         left:=1;right:=m;
112         while left<right do
113           begin
114             mid:=(left+right+1)>>1;
115             if rx[i]>x[mid] then left:=mid
116             else right:=mid-1;
117           end;
118         rr:=right;
119         for j:=ll to rr do
120           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]]);
121       end;
122     for i:=1 to m do
123       writeln(ans[i]);
124 end;
125  
126 begin
127     init;
128     work;
129 end.
pascal代码

相关文章: