题意:在一个长方形内给你n条直线,m个点,问你每个区间有多少个点
题解:对于每个点二分一下最右边的直线,就正好是这条直线左边区间之内的点。我一开始还想前缀和一下,再减出来,然后发现这两个操作正好抵消了。。。。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
using namespace std;
const int maxn = 5000+5;
const double eps = 1e-8;
const double INF = 1e20;
const double pi = acos (-1.0);
//*************基础
int cmpa(double a,double b){
if(fabs(a-b)<eps){
return 0;
}
if(a>b)return 1;
return 0;
}
int dcmp (double x) {
if (fabs (x) < eps) return 0;
return (x < 0 ? -1 : 1);
}
inline double sqr (double x) {return x*x;}
//*************点
struct Point {
double x, y;
Point (double _x = 0, double _y = 0):x(_x), y(_y) {}
void input () {scanf ("%lf%lf", &x, &y);}
void output () {printf ("%.2f %.2f\n", x, y);}
friend istream &operator >>(istream &os,Point &b){
os>>b.x>>b.y;
return os;
}
friend ostream &operator <<(ostream &os,Point &b){
os<<b.x<<' '<<b.y;
return os;
}
bool operator == (const Point &b) const {
return (dcmp (x-b.x) == 0 && dcmp (y-b.y) == 0);
}
bool operator !=(const Point &b)const{
return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0));
}
bool operator < (const Point &b) const {
return (dcmp (x-b.x) == 0 ? dcmp (y-b.y) < 0 : x < b.x);
}
double operator ^(const Point &b)const{ //叉积
return x*b.y-y*b.x;
}
Point operator + (const Point &b) const {
return Point (x+b.x, y+b.y);
}
Point operator - (const Point &b) const {
return Point (x-b.x, y-b.y);
}
Point operator * (double a) {
return Point (x*a, y*a);
}
Point operator / (double a) {
return Point (x/a, y/a);
}
double len2 () {//返回长度的平方
return sqr (x) + sqr (y);
}
double len () {//返回长度
return sqrt (len2 ());
}
double polar(){ //向量的极角
return atan2(y,x); //返回与x轴正向夹角(-pi~pi]
}
Point change_len (double r) {//转化为长度为r的向量
double l = len ();
if (dcmp (l) == 0) return *this;//零向量返回自身
r /= l;
return Point (x*r, y*r);
}
Point rotate_left () {//顺时针旋转90度
return Point (-y, x);
}
Point rotate_right () {//逆时针旋转90度
return Point (y, -x);
}
Point rotate (Point p, double ang) {//绕点p逆时针旋转ang
Point v = (*this)-p;
double c = cos (ang), s = sin (ang);
return Point (p.x + v.x*c - v.y*s, p.y + v.x*s + v.y*c);
}
Point normal () {//单位法向量
double l = len ();
return Point (-y/l, x/l);
}
};
double cross (Point a, Point b) {//叉积
return a.x*b.y-a.y*b.x;
}
double dis (Point a, Point b) {//两个点的距离
Point p = b-a; return p.len ();
}
//************直线 线段
struct Line {
Point s, e;//直线的两个点
Line () {}
Line (Point _s, Point _e) : s(_s), e(_e) {}
//一个点和倾斜角确定直线
Line (Point p, double ang) {
s = p;
if (dcmp (ang-pi/2) == 0) {
e = s + Point (0, 1);
}
else
e = s + Point (1, tan (ang));
}
//ax+by+c=0确定直线
Line (double a, double b, double c) {
if (dcmp (a) == 0) {
s = Point (0, -c/b);
e = Point (1, -c/b);
}
else if (dcmp (b) == 0) {
s = Point (-c/a, 0);
e = Point (-c/a, 1);
}
else {
s = Point (0, -c/b);
e = Point (1, (-c-a)/b);
}
}
void input () {
s.input ();
e.input ();
}
void adjust () {
if (e < s) swap (e, s);
}
double polar(){ //极角
return atan2(e.y-s.y,e.x-s.x); //返回与x轴正向夹角(-pi~pi]
}
double length () {//求线段长度
return dis (s, e);
}
double angle () {//直线的倾斜角
double k = atan2 (e.y-s.y, e.x-s.x);
if (dcmp (k) < 0) k += pi;
if (dcmp (k-pi) == 0) k -= pi;
return k;
}
Point operator &(const Line &b)const{ //求两直线交点
Point res=s;
double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x+=(e.x-s.x)*t;
res.y+=(e.y-s.y)*t;
return res;
}
};
int relation (Point p, Line l) {//点和直线的关系
//1:在左侧 2:在右侧 3:在直线上
int c = dcmp (cross (p-l.s, l.e-l.s));
if (c < 0) return 1;
else if (c > 0) return 2;
else return 3;
}
Line line[maxn];
Point point[maxn];
int ll[maxn];
int main () {
int n,m;Point s,e;
while(scanf("%d",&n)&&n){
memset(ll,0,sizeof(ll));
scanf("%d",&m);
s.input();e.input();
for(int i=1;i<=n;i++){
double ti,bi;
scanf("%lf%lf",&ti,&bi);
line[i]=Line(Point(ti,s.y),Point(bi,e.y));
}
line[++n]=Line(Point(e.x,s.y),Point(e.x,e.y));
for(int i=1;i<=m;i++){
point[i].input();
int l=1,r=n,tmp;
while(l<=r){
int mid=(l+r)/2;
if(relation(point[i],line[mid])==2){
tmp=mid;
r=mid-1;
}else l=mid+1;
}
//cout<<tmp<<endl;
ll[tmp]++;
}
for(int i=1;i<=n;i++){
printf("%d: %d\n",i-1,ll[i]);
}
printf("\n");
}
return 0;
}