• 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 }
  • 相关阅读:
    不是结束,而是刚刚开始
    第七次作业
    用类做封装
    用户故事
    团队编程--MP3播放器
    结对编程作业
    四则运算
    四、小电视自动抽奖
    三、wss连接B站弹幕
    一、基础设计
  • 原文地址:https://www.cnblogs.com/ost-xg/p/6596409.html
Copyright © 2020-2023  润新知