• 动态凸包 学习总结


    动态凸包就是可以支持动态插入点,维护凸包信息的一类问题

    又考到了,又被炸飞了(然而其实弱的连凸包性质都看不出来

    注意只能支持动态插入点,而不支持动态删除和插入

    不过删除的话如果不强制在线反过来就是插入啊OwO

    不是很喜欢水平序的动态凸包,因为要维护上下两个凸壳好烦

    所以就学了一发极角序

    大概做法是以极角序为键值用平衡树维护凸包上的点

    每次插入的时候找到插入点的前驱后继,用叉积判断是否在内部

    如果不在就插入,插入之后不断的判断插入后前驱是否在凸包内和后继是否在凸包内

    并且不断的删除直至不能删除为止

    因为只需要支持插入,删除,求前驱,求后继,所以直接用set就可以维护了

    需要注意的几个地方:

    1、一开始取的基准点必须要在凸包内部,因为只支持插入所以凸包可能变大,所以找一开始三个点的内部就可以了

    2、排序的时候极角序相同按到基准点的长度排序

    3、凸包是环状的,所以前驱和后继也是环状的,判一下就可以了

    BZOJ 2300 防线修建

    真是一道好的模板题目啊OwO

    没有下凸壳,没有边界问题,一开始还给三个点

    然而问题是写完这道题目写其他题目会被各种边界炸飞

    题目显然是要求动态删除一个点,查询凸包周长

    时间倒流一下就是动态凸包的裸题了,至于周长什么的插入删除维护一下就可以了

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<set>
    #include<cmath>
    #define eps 1e-10
    using namespace std;
     
    const int maxn=100010;
    int n,x,y,m,q;
    bool vis[maxn];
    double ans=0;
    struct Point{
        double x,y,ang,len;
        Point(double x=0,double y=0,double ang=0,double len=0):x(x),y(y),ang(ang),len(len){}
        void read(){scanf("%lf%lf",&x,&y);}
    }a[maxn],o;
    typedef Point Vector;
    bool operator <(const Point &A,const Point &B){
        if(fabs(A.ang-B.ang)<eps)return A.len<B.len;
        return A.ang<B.ang;
    }
    Vector operator -(const Point &A,const Point &B){return Vector(A.x-B.x,A.y-B.y);}
    double Cross(const Point &A,const Point &B){return A.x*B.y-A.y*B.x;}
    double Dot(const Point &A,const Point &B){return A.x*B.x+A.y*B.y;}
    double Get_len(const Point &A){return sqrt(Dot(A,A));}
    double sqr(double x){return x*x;}
    struct ASK{
        int type,u;
    }Q[maxn];
    int top=0;
    double Ans[maxn];
    set<Point>S;
    set<Point>::iterator it,pre,tmp;
     
    set<Point>::iterator Get_pre(set<Point>::iterator it){
        if(it==S.begin())it=S.end();
        it--;
        return it;
    }
    set<Point>::iterator Get_suf(set<Point>::iterator it){
        it++;
        if(it==S.end())it=S.begin();
        return it;
    }
    void Get_insert(const Point &p){
        it=S.lower_bound(p);
        if(it==S.end())it=S.begin();
        pre=Get_pre(it);
        if(Cross((*it)-(*pre),p-(*pre))>=0)return;
        ans-=Get_len((*it)-(*pre));
        ans+=Get_len(p-(*it))+Get_len(p-(*pre));
        S.insert(p);tmp=Get_pre(pre);
        while(Cross(p-(*pre),(*pre)-(*tmp))>=0){
            ans=ans-Get_len(p-(*pre))-Get_len((*pre)-(*tmp));
            ans=ans+Get_len(p-(*tmp));
            S.erase(pre);
            pre=tmp;tmp=Get_pre(pre);
        }tmp=Get_suf(it);
        while(Cross(p-(*it),(*it)-(*tmp))<=0){
            ans=ans-Get_len(p-(*it))-Get_len((*it)-(*tmp));
            ans=ans+Get_len(p-(*tmp));
            S.erase(it);
            it=tmp;tmp=Get_suf(it);
        }return;
    }
     
    int main(){
        scanf("%d%d%d",&n,&x,&y);
        a[0]=Point(0,0);a[1]=Point(n,0);a[2]=Point(x,y);
        ans+=Get_len(a[2]-a[0])+Get_len(a[2]-a[1]);
        for(int i=0;i<3;++i)o.x+=a[i].x,o.y+=a[i].y;
        o.x/=3;o.y/=3;
        for(int i=0;i<3;++i){
            a[i].ang=atan2(a[i].y-o.y,a[i].x-o.x);
            a[i].len=Get_len(a[i]-o);
            S.insert(a[i]);
        }scanf("%d",&m);
        for(int i=1;i<=m;++i){
            a[i].read();
            a[i].ang=atan2(a[i].y-o.y,a[i].x-o.x);
            a[i].len=Get_len(a[i]-o);
        }
        scanf("%d",&q);
        for(int i=1;i<=q;++i){
            scanf("%d",&Q[i].type);
            if(Q[i].type==1)scanf("%d",&Q[i].u),vis[Q[i].u]=true;
        }
        for(int i=1;i<=m;++i)if(!vis[i])Get_insert(a[i]);
        for(int i=q;i>=1;--i){
            if(Q[i].type==2)Ans[++top]=ans;
            else Get_insert(a[Q[i].u]);
        }
        for(int i=top;i>=1;--i)printf("%.2lf
    ",Ans[i]);
        return 0;
    }
    
    

    codeforces 70D

    这个是真动态凸包裸题了

    注意边界问题就好啦OwO

    代码貌似因为某些奇怪的原因找不到啦QAQ

    跟上面几乎是一模一样的

    OwO 自己计算几何太渣了

    然而NOI会不会考呢?思考ing

  • 相关阅读:
    C puzzles详解【51-57题】
    C puzzles详解【46-50题】
    C puzzles详解【38-45题】
    C puzzles详解【34-37题】
    C puzzles详解【31-33题】
    C puzzles详解【26-30题】
    C puzzles详解【21-25题】
    C puzzles详解【16-20题】
    使用C++模板实现栈的求最小值功能
    模拟求幂运算,考虑的已经很周全了
  • 原文地址:https://www.cnblogs.com/joyouth/p/5645636.html
Copyright © 2020-2023  润新知