题意:用n个分隔板把一个矩形分成n+1个部分,然后有m个点分布在这个矩形上,问每个区域上能有多少个点。
分析:利用叉乘和二分解题。首先预处理出这些分隔板,然后对每个点进行二分,二分条件是看当前要判断的点在隔板的左还是右,而利用叉乘正好可以判断点在左还是右边。
参考代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 5e3+5;
int n,m,px1,py1,px2,py2;
struct Point{
int x,y;
Point(){}
Point( int xx, int yy)
{
x = xx;
y = yy;
}
Point operator - ( const Point &p)const
{
return Point(x-p.x,y-p.y);
}
int operator * ( const Point &p)const
{
return x*p.y-y*p.x;
}
};
struct Line{
Point s,e;
Line(){}
Line( Point ss, Point ee)
{
s = ss;
e = ee;
}
};
Line line[maxn];
int ans[maxn];
//叉乘计算,返回p1p2×p1p3
int xmult( Point p1, Point p2, Point p3)
{
return (p2-p1)*(p3-p1);
}
int main()
{
int flag = 0;
while( ~scanf("%d",&n) && n)
{
if( flag)
puts("");
flag = 1;
scanf("%d%d%d%d%d",&m,&px1,&py1,&px2,&py2);
for( int i = 0; i < n; i++)
{
int ui,li;
scanf("%d%d",&ui,&li);
line[i] = Line(Point(ui,py1),Point(li,py2));//把每个隔板看成一条线
}
line[n] = Line(Point(px2,py1),Point(px2,py2));
mem(ans,0);
while( m--)
{
int x,y;
scanf("%d%d",&x,&y);
Point p = Point(x,y);
int l = 0;
int r = n;
int tmp;
while( l <= r)
{
int mid = (l+r)>>1;
if( xmult(p,line[mid].s,line[mid].e) < 0)
{
tmp = mid;
r = mid-1;
}
else
l = mid+1;
}
ans[tmp]++;
}
for( int i = 0; i <= n; i++)
printf("%d: %d\n",i,ans[i]);
}
return 0;
}