• [HAOI2011] 防线修建


    给定 (n) 个点,有 (m) 次操作,每次指定一个点将其删去,或询问当前上凸包的周长。有 ((0,0),(n,0),(x,y)) 三个点不会被删去,且所有点的 (x) 坐标都位于 ((0,n)),所有点的 (y) 坐标都位于 ((0,+infty))

    Solution

    逆序处理,就是一个动态凸包的裸题

    注意可能会有重复,要先处理一下

    有些没被删过的点要提前先加进去

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 200005;
    
    struct point {
        int x,y;
        point(){}
        point(int a,int b){x=a;y=b;}
        bool operator != (const point &a) const {return (x!=a.x)||(y!=a.y);};
        bool operator < (const point &a) const {return (x==a.x)?(y<a.y):(x<a.x);}
        point operator - (const point &a) const {return point(x-a.x,y-a.y);}
        int operator * (const point &a) const {return x*a.y-y*a.x;}
    } p[N];
    
    double dis(point a,point b) {return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));}
    set<point> s;
    double ans;
    int n;
    
    void add(point p) {
        point a,b,c;
        auto it=s.upper_bound(p);
        b=*it;
        --it;
        a=*it;
        if(p.x==b.x || (p-a)*(b-p)>=0) return;
        ans-=dis(a,b);
        while(a!=(point){0,0}) {
            it--; c=*it;
            if((a-c)*(p-a)>=0) {
                ans-=dis(a,c);
                s.erase(s.find(a));
                a=c;
            }
            else break;
        }
        it=s.find(b);
        while(b!=(point){n,0}) {
            it++; c=*it;
            if((b-p)*(c-b)>=0) {
                ans-=dis(b,c);
                s.erase(s.find(b));
                b=c;
            }
            else break;
        }
        ans+=dis(a,p)+dis(p,b);
        s.insert(p);
    }
    
    int m,q,x[N],y[N],X,Y,fg[N];
    vector <double> o;
    
    signed main() {
        cin>>n>>X>>Y>>m;
        s.insert({0,0});
        s.insert({n,0});
        s.insert({X,Y});
        ans=dis((point){0,0},(point){X,Y})+dis((point){n,0},(point){X,Y});
        for(int i=1;i<=m;i++) {
            cin>>p[i].x>>p[i].y;
        }
        cin>>q;
        for(int i=1;i<=q;i++) {
            cin>>x[i];
            if(x[i]==1) {
                cin>>y[i];
                if(fg[y[i]]==0) {
                    fg[y[i]]=1;
                }
                else x[i]=0;
            }
        }
        for(int i=1;i<=m;i++) if(fg[i]==0) add(p[i]);
        for(int i=q;i>=1;--i) {
            if(x[i]==1) {
                add(p[y[i]]);
            }
            if(x[i]==2) {
                o.push_back(ans);
            }
        }
        while(o.size()) printf("%.2lf
    ",o.back()), o.pop_back();
    }
    
    
  • 相关阅读:
    Python入门基础知识点(基础数据类型之字典)
    Python入门基础知识点(基础数据类型之二)
    Python入门基础知识点(基础数据类型)
    Python入门基础知识点(循环语句和编码)
    Python入门基础知识点(基础语法介绍)
    接口继承
    类的继承
    类的组合
    静态属性、类方法、静态方法
    类与对象属性的操作
  • 原文地址:https://www.cnblogs.com/mollnn/p/12391425.html
Copyright © 2020-2023  润新知