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

题意:判断一堆小点有多少个在任意三个大点构成的三角形里面。

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

代码:

  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 }
原文地址:https://www.cnblogs.com/ost-xg/p/6596409.html