SGU 253 log(n)判点在凸包内 二分

来源:互联网 发布:json html 示例输出 编辑:程序博客网 时间:2024/05/21 08:56

水平序和极角序都可以,极角序相对方便

用极角序的,直接二分就可以了。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;typedef long long ll;const double eps = 1e-8;const int maxn = 100005;struct Point {    double x, y;}p[maxn];int n, m, k;double cross(Point o, Point a, Point b) {    return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);}bool binary(Point *p, Point &tp) {//条件:p点集必须是顺时针或者逆时针//(注意3点共线下的点也必须满足这个条件)//(如果有3点共线极角序不能完成该条件)    int l = 0, r = n-1;    while(l < r) {        int m = l+r >> 1;        int c1 = cross(p[0], p[m], tp);        int c2 = cross(p[0], p[(m+1)%n], tp);        int c3 = cross(p[m], p[(m+1)%n], tp);        if(c1 >= 0 && c2 <= 0 && c3 >= 0)        return true;        if(c1 >= 0) l = m+1;        else r = m;    }    return false;}int main() {    int i;    scanf("%d%d%d", &n, &m, &k);        for(i = 0; i < n; i++)            scanf("%lf%lf", &p[i].x, &p[i].y);        int cnt = 0;        p[n] = p[0];        while(m--) {            Point tp;            scanf("%lf%lf", &tp.x, &tp.y);            cnt += binary(p, tp);        }        if(cnt >= k) puts("YES");        else puts("NO");    return 0;}



用水平序做的,我的做法还要对点排序和求上下凸包,

还是写搓了,不想写极角序了。


#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;#define LL __int64int n, m, k;struct point {int x, y;void in() {scanf("%d%d", &x, &y);}bool operator < (const point &t) const{    return y < t.y || (y == t.y && x < t.x);}bool operator == (const point &t) const {        return x == t.x && y == t.y;}}p[100005];LL cross(point o, point a, point b) {return (LL)(a.x-o.x)*(b.y-o.y)-(LL)(a.y-o.y)*(b.x-o.x);}point up[100005], down[100005]; // 水平序后的上下凸包int top, sum1, sum2;void convex() {top = 0;int i, j;for(i = 0; i < n; i++) {while(top >= 2 && cross(down[top-2], down[top-1], p[i]) < 0) top--;down[top++] = p[i];}sum2 = top;top = 0;for(i = n-1; i >= 0; i--) {while(top >= 2 && cross(up[top-2], up[top-1], p[i]) < 0) top--;up[top++] = p[i];}sum1 = top;reverse(up, up+sum1); // 为了后面的lower_bound}int main() {int i, j;scanf("%d%d%d", &n, &m, &k);for(i = 0; i < n; i++) p[i].in();sort(p, p+n);convex();int cnt = 0;while(m--) {point tp;tp.in();if(tp == p[0] ) { cnt++; continue; } // 注意最左下角的点要特判int j = lower_bound(up, up+sum1, tp) - up-1; //找点tp在点j和点j+1之间if(j >= sum1-1 || j < 0) continue;bool g1 = cross(up[j], up[j+1], tp) <= 0;j = lower_bound(down, down+sum2, tp) - down-1; //找点tp在点j和点j+1之间if(j >= sum2-1 || j < 0) continue;bool g2 = cross(down[j], down[j+1], tp) >= 0;if(g1 && g2) cnt++;}if(cnt >= k) puts("YES");else puts("NO");return 0;}


原创粉丝点击