Gym 100883Jpalprime(二分判断点在凸包里)

来源:互联网 发布:绝地游戏画面优化 编辑:程序博客网 时间:2024/06/05 04:02
题意:判断一堆小点有多少个在任意三个大点构成的三角形里面。

思路:其实就是判断点在不在凸包里面,判断的话可以使用二分来判断,就是判断该点在凸包的哪两个点和起点的连线之间。

 

代码:

  1 /** @xigua */  2 #include<cstdio>  3 #include<cmath>  4 #include<iostream>  5 #include<algorithm>  6 #include<vector>  7 #include<stack>  8 #include<cstring>  9 #include<queue> 10 #include<set> 11 #include<string> 12 #include<map> 13 #include<climits> 14 #define PI acos(-1) 15 using namespace std; 16 typedef long long ll; 17 typedef double db; 18 const int maxn = 5e4 + 5; 19 const int mod = (1 << 31) - 1; 20 const int INF = 1e8 + 5; 21 const ll inf = 1e15 + 5; 22 const db eps = 1e-6; 23  24 struct Node { 25     ll x, y, id; 26 } po[maxn]; 27 int n; 28 int flag; 29  30 bool cmp(const Node &a, const Node &b) { 31     if (a.x == b.x) return a.y < b.y; 32     return a.x < b.x; 33 } 34  35 ll mul(ll x1, ll x2, ll y1, ll y2) { 36     return x1 * y2 - x2 * y1; 37 } 38 Node S[maxn]; 39 int top; 40  41 void ch(Node cur) { 42     while (top > flag) { 43         Node po1 = S[top]; 44         Node po2 = S[top-1]; 45         ll x1 = po1.x - po2.x, y1 = po1.y - po2.y; 46         ll x2 = cur.x - po2.x, y2 = cur.y - po2.y; 47         if (mul(x1, x2, y1, y2) >= 0) { 48             top--; 49         } 50         else break; 51     } 52     S[++top] = cur; 53 } 54  55 int ok(int mid, ll x, ll y) { 56     ll x1 = S[mid].x - S[1].x, y1 = S[mid].y - S[1].y; 57     ll x2 = x - S[1].x, y2 = y - S[1].y; 58     ll tmp = mul(x1, x2, y1, y2); 59     if (tmp > 0) return 1; 60     if (tmp == 0) return 2; 61     return 0; 62 } 63  64 void solve() { 65     while (cin >> n) { 66         for (int i = 1; i <= n; i++) { 67             scanf("%I64d%I64d", &po[i].x, &po[i].y); 68             po[i].id = i; 69         } 70         sort(po+1, po+1+n, cmp); 71         top = 0; 72         flag = 1; 73         for (int i = 1; i <= n; i++) { 74             ch(po[i]); 75         } 76         flag = top; 77         for (int i = n-1; i >= 1; i--) { 78             ch(po[i]); 79         } 80         top--; 81         int q, ans = 0; cin >> q; 82         Node tmp[maxn]; 83         for (int i = 1; i <= top; i++) 84             tmp[i] = S[i]; 85         for (int i = 2; i <= top; i++) 86             S[i] = tmp[top-i+2]; 87         while (q--) { 88             ll x, y; 89             scanf("%I64d%I64d", &x, &y); 90             int l = 2, r = top; //二分上界和下界 91             while (l < r) { 92                 int mid = l + r + 1 >> 1; 93                 if (ok(mid, x, y))  //在当前这条线之上 94                     l = mid; 95                 else r = mid - 1; 96             } 97             if (l == top) { //在上界需要特殊判断 98                 if (ok(l, x, y) == 2) { 99                     ll a = x - S[1].x, b = y - S[1].y;100                     ll dis1 = a * a + b * b;101                     a = S[l].x - S[1].x, b = S[l].y - S[1].y;102                     ll dis2 = a * a + b * b;103                     if (dis1 <= dis2) ans++;104                 }105                 continue;106             }107             Node xx[5];108             xx[1] = S[1], xx[2] = S[l], xx[3] = S[l+1], xx[4] = S[1];109             ll are1 = 0;110             for (int i = 1; i <= 3; i++) {111                 ll x1 = xx[i].x - x, y1 = xx[i].y - y;112                 ll x2 = xx[i+1].x - x, y2 = xx[i+1].y - y;113                 ll tmp = mul(x1, x2, y1, y2);114                 if (tmp < 0) tmp = -tmp;115                 are1 += tmp;116             }117             ll x1 = xx[2].x - xx[1].x, y1 = xx[2].y - xx[1].y;118             ll x2 = xx[3].x - xx[1].x, y2 = xx[3].y - xx[1].y;119             ll are2 = mul(x1, x2, y1, y2);120             //if (are1 < 0) are1 = -are1;121             if (are2 < 0) are2 = -are2;122             if (are2 == are1) ans++;    //通过面积来判断,are1代表的是加上该点的123         }124         cout << ans << endl;125     }126 }127 128 int main() {129     //cin.sync_with_stdio(false);130     //freopen("in.txt", "r", stdin);131     //freopen("isharp.out", "w", stdout);132     int t  = 1; //cin >> t;133 134     while (t--) {135         solve();136     }137     return 0;138 }

 

原创粉丝点击