Description
Input
Output
Sample Input
5 6 0 10 60 0 3 1 4 3 6 8 10 10 15 30 1 5 2 1 2 8 5 5 40 10 7 9 4 10 0 10 100 0 20 20 40 40 60 60 80 80 5 10 15 10 25 10 35 10 45 10 55 10 65 10 75 10 85 10 95 10 0
Sample Output
0: 2 1: 1 2: 1 3: 1 4: 0 5: 1 0: 2 1: 2 2: 2 3: 2 4: 2
Hint
记玩具在点p0,某块板的上边点是p1,下边点是p2,p2p1(向量)×p2p0>0表示p0在p1p2的左面,<0表示在右面。接下来就是用二分法找出每个点所在的分区。
叉积+二分查找
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; const int N = 1e6+10, M = 30005, mod = 1e9 + 7, inf = 0x3f3f3f3f; typedef long long ll; int n,m,x1,x2,y11,y2,ans[N],t1,t2; struct point{int x,y;}; struct segment{point a,b;}s[N]; point sub(point a,point b) {//向量 point t; t.x = a.x-b.x; t.y = a.y-b.y; return t; } int cross(point a,point b){//叉积公式 return a.x*b.y-b.x*a.y; } int turn(point p1,point p2,point p3){ //叉积 return cross(sub(p2,p1),sub(p3,p1)); } void searchs(point x) { int l=1,r=n,mid,t=0; while(l<=r) { mid = (l+r)>>1; if(turn(s[mid].a,s[mid].b,x) >= 0) { t = mid;l=mid+1; } else r = mid-1; } ans[t]++; } int main() { while(scanf("%d",&n)&&n) { memset(ans,0,sizeof(ans)); scanf("%d%d%d%d%d",&m,&x1,&y11,&x2,&y2); for(int i=1;i<=n;i++){ scanf("%d%d",&t1,&t2); s[i].a.x=t1;s[i].a.y=y11; s[i].b.x=t2;s[i].b.y=y2; } for(int i=1;i<=m;i++) { point t; scanf("%d%d",&t.x,&t.y); searchs(t); } for(int i=0;i<=n;i++) printf("%d: %d\n",i,ans[i]); printf("\n"); } }
原文:http://www.cnblogs.com/zxhl/p/5247611.html