1199: [HNOI2005]汤姆的游戏

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代码
  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 
  5 typedef double ld;
  6 
  7 const int maxn=250010;
  8 const int maxm=10010;
  9 const ld eps=1e-7;
 10 
 11 int n,m,ans[maxm];
 12 
 13 struct REC
 14 {
 15     ld lx,ly,rx,ry;
 16 }rec[maxn];
 17 int numr;
 18 
 19 struct CIR
 20 {
 21     ld x,y,r;
 22 }cir[maxn];
 23 int numc;
 24 
 25 struct point
 26 {
 27     ld x,y;
 28     int k;
 29 }d[maxm];
 30 
 31 int operator < (const point & a,const point & b)
 32 {
 33     return a.x<b.x;
 34 }
 35 
 36 int main()
 37 {
 38     int i,j;
 39     scanf("%d%d",&n,&m);
 40     char s;
 41     for(i=1;i<=n;++i)
 42     {
 43         scanf("%s",&s);
 44         if(s=='r')
 45         {
 46             ++numr;
 47             scanf("%lf%lf%lf%lf",&rec[numr].lx,&rec[numr].ly,&rec[numr].rx,&rec[numr].ry);
 48             if(rec[numr].lx>rec[numr].rx)
 49                 swap(rec[numr].lx,rec[numr].rx);
 50             if(rec[numr].ly>rec[numr].ry)
 51                 swap(rec[numr].ly,rec[numr].ry);
 52         }
 53         else
 54         {
 55             ++numc;
 56             scanf("%lf%lf%lf",&cir[numc].x,&cir[numc].y,&cir[numc].r);
 57         }
 58     }
 59     for(i=1;i<=m;++i)
 60     {
 61         scanf("%lf%lf",&d[i].x,&d[i].y);
 62         d[i].k=i;
 63     }
 64     sort(d+1,d+m+1);
 65     int left,right,ll,rr,mid;
 66     for(i=1;i<=numr;++i)
 67     {
 68         left=1,right=m;
 69         while(left<right)
 70         {
 71             mid=(left+right)/2;
 72             if(d[mid].x>rec[i].lx)right=mid;
 73             else left=mid+1;
 74         }
 75         ll=left;
 76         left=1;right=m;
 77         while(left<right)
 78         {
 79             mid=(left+right+1)/2;
 80             if(d[mid].x<rec[i].rx)left=mid;
 81             else right=mid-1;
 82         }
 83         rr=right;
 84         for(j=ll;j<=rr;++j)
 85             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))
 86             ++ans[d[j].k];
 87     }
 88     for(i=1;i<=numc;++i)
 89     {
 90         left=1;right=m;
 91         while(left<right)
 92         {
 93             mid=(left+right)/2;
 94             if(d[mid].x>cir[i].x-cir[i].r)right=mid;
 95             else left=mid+1;
 96         }
 97         ll=left;
 98         left=1;right=m;
 99         while(left<right)
100         {
101             mid=(left+right+1)/2;
102             if(cir[i].x+cir[i].r>d[mid].x)left=mid;
103             else right=mid-1;
104         }
105         rr=right;
106         for(j=ll;j<=rr;++j)
107             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))
108             ++ans[d[j].k];
109     }
110     for(i=1;i<=m;++i)
111         printf("%d
",ans[i]);
112     return 0;
113 }
C++代码
原文地址:https://www.cnblogs.com/Randolph87/p/3594524.html