• 洛谷 P2521 [HAOI2011]防线修建 (动态凸包,凸包性质 + set)


    题目:传送门

    题意

     

     

    思路

    每次询问 1 都是删除 1 个点,由于删除点对凸包的影响比较难搞,所以,我们可以用离线做法,将询问逆着来做,这样,每次询问 1 就相当于加入一个点,加入一个点对凸包的影响,是比较好维护的,可以用 set 存当前凸包的点,具体细节看代码。

    #include <bits/stdc++.h>
    #define LL long long
    #define ULL unsigned long long
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF INT_MAX
    #define inf LLONG_MAX
    #define PI acos(-1)
    #define fir first
    #define sec second
    using namespace std;
    
    const int N = 1e6 + 5;
    const double eps = 1e-10;
    
    struct Point {
        double x, y;
        Point(double x = 0, double y = 0) : x(x), y(y) { }
    };
    
    Point operator + (Point A, Point B) { return Point(A.x + B.x, A.y + B.y); }
    Point operator - (Point A, Point B) { return Point(A.x - B.x, A.y - B.y); }
    Point operator * (Point A, double p) { return Point(A.x * p, A.y * p); }
    Point operator / (Point A, double p) { return Point(A.x / p, A.y / p); }
    double Cross(Point A, Point B) { return A.x * B.y - A.y * B.x; }
    double Dot(Point A, Point B) { return A.x * B.x + A.y * B.y; }
    double Length(Point A) { return sqrt(Dot(A, A)); }
    
    int dcmp(double x) {
        if(fabs(x) < eps) return 0; return x < 0 ? -1 : 1;
    }
    
    bool operator < (Point A, Point B) {
        return A.x < B.x || (A.x == B.x && A.y < B.y);
    }
    
    double dis(Point A, Point B) { return Length(B - A); }
    
    double ans = 0.0;
    
    Point p[N];
    
    bool vis[N];
    
    double Ans[N];
    
    int id[N], pos[N];
    
    set < Point > Q;
    
    void add(Point tmp) {
        set < Point >::iterator l, r, t;
        l = r = Q.upper_bound(tmp);
        l--;
    
        if(dcmp(Cross(*r - *l, *r - tmp)) > 0) return ; /// 点在凸包内,即向量 tmp->r 在向量 l->r 的左边
    
        ans -= dis(*l, *r);
    
        while(l != Q.begin()) {
            t = l; t--;
            if(dcmp(Cross(*l - tmp, *t - tmp)) > 0) break; /// 满足凸包性质
            ans -= dis(*l, *t);
            Q.erase(*l); l = t;
        }
    
        while(1) {
            t = r; t++;
            if(t == Q.end() || dcmp(Cross(*t - tmp, *r - tmp)) > 0) break; /// 满足凸包性质
            ans -= dis(*r, *t);
            Q.erase(r); r = t;
        }
        Q.insert(tmp);
        l = r = Q.find(tmp);
        l--; r++;
        ans += dis(tmp, *l) + dis(tmp, *r);
    }
    
    int main() {
    
        int n, m;
        double x, y;
        scanf("%d %lf %lf", &n, &x, &y);
        scanf("%d", &m);
    
        rep(i, 1, m) scanf("%lf %lf", &p[i].x, &p[i].y);
    
        Q.insert(Point(0, 0));
        Q.insert(Point(n, 0));
        Q.insert(Point(x, y));
    
        ans += dis(Point(0, 0), Point(x, y));
        ans += dis(Point(n, 0), Point(x, y));
    
        int q; scanf("%d", &q);
    
        rep(i, 1, q) {
            scanf("%d", &id[i]);
            if(id[i] == 1) {
                scanf("%d", &pos[i]);
                vis[pos[i]] = 1;
            }
        }
    
        rep(i, 1, m) if(!vis[i]) add(p[i]);
    
        dep(i, 1, q) {
            if(id[i] == 1) add(p[pos[i]]);
            else Ans[i] = ans;
        }
    
        rep(i, 1, q) if(id[i] == 2) printf("%.2f
    ", Ans[i]);
    
        return 0;
    }
    一步一步,永不停息
  • 相关阅读:
    作业day17
    python开发学习day17 (生成器;面向过程;三元表达式;生成式,内置函数)
    作业day16
    python开发学习day16 (三层装饰器;迭代器)
    python开发学习day15 (叠加装饰器;递归调用;匿名函数)
    作业day14
    python开发学习day14 (装饰器;语法糖;装饰器模板)
    python开发学习day13 (函数嵌套;名称空间与作用域;闭包函数)
    作业day12
    Python-简单算法程序
  • 原文地址:https://www.cnblogs.com/Willems/p/12563347.html
Copyright © 2020-2023  润新知