[HAOI2011] 防线修建 - 动态凸包,set

Posted mollnn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HAOI2011] 防线修建 - 动态凸包,set相关的知识,希望对你有一定的参考价值。

给定 (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();
}

以上是关于[HAOI2011] 防线修建 - 动态凸包,set的主要内容,如果未能解决你的问题,请参考以下文章

HAOI2011 防线修建

BZOJ2300[HAOI2011]防线修建 set维护凸包

[日常摸鱼]Luogu2521[HAOI2011]防线修建-set维护凸包

Luogu-2521 [HAOI2011]防线修建

bzoj千题计划236:bzoj2300: [HAOI2011]防线修建

bzoj2300[HAOI2011]防线修建 离线+STL-set维护凸包