• 计算几何专题训练


    • 牛客多校10 J Illuminations

    点到凸包切点,转换为求环上最少区间进行覆盖

    #include <bits/stdc++.h>
    
    using namespace std;
    const double eps = 1e-15;
    
    inline static int dcmp(double x) { return x < -eps ? -1 : x > eps ? 1 : 0; }
    
    struct xl {
        double x, y;
        int id;
    
        xl() {}
    
        void in() {
            scanf("%lf%lf", &x, &y);
        }
    
        xl(double x, double y) : x(x), y(y) {}
    
        xl operator+(const xl &rhs) const { return xl(x + rhs.x, y + rhs.y); }
    
        xl operator-(const xl &rhs) const { return xl(x - rhs.x, y - rhs.y); }
    
        xl operator*(const double &rhs) const { return xl(x * rhs, y * rhs); }
    
        xl operator/(const double &rhs) const { return xl(x / rhs, y / rhs); }
        
        double angle(){return atan2(y,x);}
    
    };
    double D_(const xl &a, const xl &b) {
        return a.x * b.x + a.y * b.y;
    }
    
    double X_(const xl &a, const xl &b) {
        return a.x * b.y - a.y * b.x;
    }
    
    double onleft(xl &a, xl &b, xl &c) {
        return X_(b - a, c - a);
    }
     
    int n, m;
    xl a[400020];
    xl b[200020];
    xl base;
    int you(xl q) {
        int ret = 0;
        int lo = 1, hi = n - 1;
        while (lo <= hi) {
            bool dnl = onleft(q, a[lo + 1], a[lo]) > 0;
            int mid = (lo + hi + 1) >> 1;
            bool dnm = onleft(q, a[mid + 1], a[mid]) > 0;
            if (dnm) {
                if (onleft(q, a[ret], a[mid]) > 0)
                    ret = mid;	
            }
            if (dnl) {
                if (onleft(q, a[ret], a[lo]) > 0)
                    ret = lo;
                if (dnm && onleft(q, a[lo], a[mid]) > 0)
                    hi = mid - 1;
                else lo = mid + 1;
            } else {
                if (!dnm && onleft(q, a[lo], a[mid]) > 0)
                    lo = mid + 1;
                else hi = mid - 1;
            }
        }
        return ret == 0 ? n : ret;
    }
    int zuo(xl q)
    {
        int ret = 0;
        int lo = 1, hi = n - 1;
        while (lo <= hi) {
            bool dnl = onleft(q, a[lo - 1], a[lo]) < 0;
            int mid = (lo + hi + 1) >> 1;
            bool dnm = onleft(q, a[mid - 1], a[mid]) < 0;
            if (dnm) {
                if (onleft(q, a[ret], a[mid]) < 0)
                    ret = mid;
            }
            if (dnl) {
                if (onleft(q, a[ret], a[lo]) < 0)
                    ret = lo;
                if (dnm && onleft(q, a[lo], a[mid]) < 0)
                    lo = mid + 1;
                else hi = mid - 1;
            } else {
                if (!dnm && onleft(q, a[lo], a[mid]) < 0)
                    hi = mid - 1;
                else lo = mid + 1;
            }
        }
        return ret == 0 ? n : ret;
    }
    struct wocao {
        int l, r;
        int id;
    
        wocao() {}
    
        wocao(int ll, int rr, int iid) {
            if (rr < ll)rr += n;
            l = ll;
            r = rr;
            id = iid;
        }
    
        bool operator<(const wocao &rhs) const {
            return l == rhs.l ? r > rhs.r : l < rhs.l;
        }
    };
    wocao q[400020];
    int nima[400040][22];
    int main() {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)a[i].in();
        a[0] = a[n];
        base = a[1];
        for (int i = 1; i <= m; i++)
        {
    		b[i].in(), b[i].id = i;
    		q[i]=wocao(you(b[i]),zuo(b[i]),i);
    	}
        sort(q + 1, q + m + 1);
        int Max = 0, ed = 0;
        for (int i = 1; i <= m; i++) {
            if (q[i].r <= Max)continue;
            else {
                Max = q[i].r;
                q[++ed] = q[i];
            }
        }
        m = ed;
        for (int i = 1; i <= m; i++)q[i + m] = wocao(q[i].l + n, q[i].r + n, q[i].id);
        for (int i = 1; i <= m; i++)
            if (q[i + 1].l > q[i].r) {
                puts("-1");
                exit(0);
            }
        if(q[m].r-q[1].l<n)
        {
        	puts("-1");
        	exit(0);
        }
        int now = 1;
        for (int i = 1; i <= 2 * m; i++) {
            while (q[now].l <= q[i].r && now <= 2 * m)now++;
            nima[i][0] = now - 1;
        }
        for (int k = 1; k <= 19; k++) {
            for (int i = 1; i <= 2 * m; i++) {
                nima[i][k] = nima[nima[i][k - 1]][k - 1];
            }
        }
        int ans = m + 1, o;
        for (int i = 1; i <= m; i++) {
            if(q[nima[i][18]].r-q[i].l<n)continue;
            now=i;
            int temp=0;
            for(int j=18;j>=0;j--)
            {
                if(q[nima[now][j]].r-q[i].l<n)
                    now=nima[now][j],temp+=1<<j;
            }
            if(temp + 1<ans)ans=temp+1,o=i;
        }
        cout << ans + 1 << "
    ";
        now = o;
        for (int i = 0; i <= ans; i++) {
            printf("%d ", q[now].id);
            now = nima[now][0];
        }
        return 0;
    }
    /*
    7
    2
    0 0
    2 1
    3 2
    4 4
    3 6
    2 7
    0 8
    
    9 4
    -1 1
    
    3 4
    0 0
    1 0
    0 1
    2 2
    -1 3
    -1 -1
    -0.5 -0.5
    */
    
    • gym101201 E Enclosure

    求在原来凸包的基础上增加一个点的新凸包面积的最大值。
    倍增预处理凸包上点(i)往后(1<<k)个点形成的多边形面积,求出其他点在凸包上的切点(L,R),用三角形面积减小多边形面积即是增加的面积。

    #include <bits/stdc++.h>
    
    using namespace std;
    const double eps = 1e-15;
    
    inline static int dcmp(double x) { return x < -eps ? -1 : x > eps ? 1 : 0; }
    
    struct xl {
        long long x{}, y{};
        int id{};
    
        xl() {}
    
        void in() {
            scanf("%lld%lld", &x, &y);
        }
    
        xl(long long x, long long y) : x(x), y(y) {}
    
        xl operator+(const xl &rhs) const { return {x + rhs.x, y + rhs.y}; }
    
        xl operator-(const xl &rhs) const { return {x - rhs.x, y - rhs.y}; }
    
        bool operator<(const xl &rhs) const {
            return x == rhs.x ? y < rhs.y : x < rhs.x;
        }
    };
    
    long long D_(const xl &a, const xl &b) {
        return a.x * b.x + a.y * b.y;
    }
    
    long long X_(const xl &a, const xl &b) {
        return a.x * b.y - a.y * b.x;
    }
    
    long long onleft(xl &a, xl &b, xl &c) {
        return X_(b - a, c - a);
    }
    
    int n, k, blen;
    vector<xl> b, c;
    
    int you(xl q) {
        int ret = 0;
        int lo = 1, hi = blen - 1;
        while (lo <= hi) {
            bool dnl = onleft(q, b[lo + 1], b[lo]) > 0;
            int mid = (lo + hi + 1) >> 1;
            bool dnm = onleft(q, b[mid + 1], b[mid]) > 0;
            if (dnm) {
                if (onleft(q, b[ret], b[mid]) > 0)
                    ret = mid;
            }
            if (dnl) {
                if (onleft(q, b[ret], b[lo]) > 0)
                    ret = lo;
                if (dnm && onleft(q, b[lo], b[mid]) > 0)
                    hi = mid - 1;
                else lo = mid + 1;
            } else {
                if (!dnm && onleft(q, b[lo], b[mid]) > 0)
                    lo = mid + 1;
                else hi = mid - 1;
            }
        }
        return ret;
    }
    
    int zuo(xl q) {
        int ret = 0;
        int lo = 1, hi = blen - 1;
        while (lo <= hi) {
            bool dnl = onleft(q, b[lo - 1], b[lo]) < 0;
            int mid = (lo + hi + 1) >> 1;
            bool dnm = onleft(q, b[mid - 1], b[mid]) < 0;
            if (dnm) {
                if (onleft(q, b[ret], b[mid]) < 0)
                    ret = mid;
            }
            if (dnl) {
                if (onleft(q, b[ret], b[lo]) < 0)
                    ret = lo;
                if (dnm && onleft(q, b[lo], b[mid]) < 0)
                    lo = mid + 1;
                else hi = mid - 1;
            } else {
                if (!dnm && onleft(q, b[lo], b[mid]) < 0)
                    hi = mid - 1;
                else lo = mid + 1;
            }
        }
        return ret;
    }
    
    xl a[100010];
    
    void hull(vector<xl> &ret, int m) {
        sort(a + 1, a + m + 1);
        int rm = 0;
        for (int i = 1; i <= m; i++) {
            while (rm > 1 && dcmp(X_(ret[rm - 1] - ret[rm - 2], a[i] - ret[rm - 2])) < 0)ret.pop_back(), rm--;
            ret.push_back(a[i]), rm++;
        }
        int kk = rm;
        for (int i = m - 1; i >= 1; i--) {
            while (rm > kk && dcmp(X_(ret[rm - 1] - ret[rm - 2], a[i] - ret[rm - 2])) < 0)ret.pop_back(), rm--;
            ret.push_back(a[i]), rm++;
        }
        if (m > 1)rm--, ret.pop_back();
    }
    
    long long area[200010][20];//16
    int main() {
        cin >> n >> k;
        for (int i = 1; i <= n; i++)a[i].in();
        hull(b, k);
        blen = b.size();
        for (int i = 0; i < blen; i++)b.push_back(b[i]);
        hull(c, n);
        for (int i = 0; i < 2 * blen; i++)area[i][0] = 0;
        for (int i = 1; i <= 16; i++) {
            for (int j = 0; j < 2 * blen; j++)
                if (j + (1 << i) < 2 * blen) {
                    int mid = j + (1 << (i - 1));
                    area[j][i] = area[j][i - 1] + area[mid][i - 1] +
                                 abs(X_(b[mid] - b[j], b[mid] - b[j + (1 << i)]));
                } else break;
        }
        long long ans = 0;
        for (auto x:c) {
            int l = you(x);
            int r = zuo(x);
            if (l == r)continue;
            long long ar = abs(X_(x - b[l], x - b[r]));
            if (r < l)r += blen;
            int cha = r - l;
            long long temp = 0;
            for (int i = 16; i >= 0; i--)
                if (cha & (1 << i)) {
                    int mid = l + (1 << i);
                    temp += abs(X_(b[l] - b[mid], b[mid] - b[r])) + area[l][i];
                    l = mid;
                }
            ans = max(ans, -temp + ar);
        }
        for (int i = 2; i < blen; i++)
            ans += abs(X_(b[i] - b[i - 1], b[i] - b[0]));
    //    for (int i = 0; i < blen; i++)cerr << b[i].x << " " << b[i].y << "
    ";
        printf("%lld.%lld", ans / 2, ans % 2 ? 5 : 0);
        return 0;
    }
    
    
  • 相关阅读:
    vue中使用ztree时报找不到init方法错的解决方案
    element-ui 自定义表单验证 , 但是不出现小红心解决方案
    iframe子页面与父页面之间通信
    GSS系列题解——最大子段和系列
    平衡树 区间树 学习
    数据结构:从入门到精通
    后缀数组
    2019元旦总结,迎接2019
    网络流+费用流 学习
    SLT学习——leafes tree扩展 【文艺平衡树】
  • 原文地址:https://www.cnblogs.com/HugeGun/p/15157311.html
Copyright © 2020-2023  润新知