bzoj2300 [HAOI2011]防线修建(动态维护凸包)

把操作离线,倒着做,这样就是加点维护凸包了。
可以用set维护一下当前凸包上的点
然后每次新加一个点时判断是在凸包内还是凸包外
如果在凸包外,就要重新维护上凸壳,往两边删点,直到再次构成凸壳。
O ( n l o g n )

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m;
double ans=0;
inline double sqr(double x){return x*x;}
struct P{
    double x,y;
    P(double _x=0,double _y=0){x=_x;y=_y;}
    friend bool operator<(P a,P b){return a.x==b.x?a.y<b.y:a.x<b.x;}
    friend double dis(P a,P b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
    friend double det(P a,P b){return a.x*b.y-a.y*b.x;}
    friend P operator-(P a,P b){return P(a.x-b.x,a.y-b.y);}
}a[N],O,T;
bool mk[N];
struct quer{
    int op,id;
}qq[N<<1];
set<P>st;set<P>::iterator it,pre,succ;
vector<double>Ans;
inline void ins(P x){
    succ=st.lower_bound(x);
    pre=succ;--pre;
    if(det(x-*pre,*succ-*pre)>0) return;
    ans-=dis(*pre,*succ);
    while(1){
        it=succ;++succ;
        if(succ==st.end()) break;
        if(det(*succ-x,*it-x)>0) break;
        ans-=dis(*it,*succ);st.erase(it);
    }while(1){
        if(pre==st.begin()) break;
        it=pre;--pre;
        if(det(*it-x,*pre-x)>0) break;
        ans-=dis(*it,*pre);st.erase(it);
    }succ=st.lower_bound(x);pre=succ;--pre;
    ans+=dis(x,*pre);ans+=dis(x,*succ);st.insert(x);
}
int main(){
//  freopen("a.in","r",stdin);
    T.x=read();st.insert(O);st.insert(T);
    P cap;cap.x=read();cap.y=read();st.insert(cap);
    ans+=dis(O,cap);ans+=dis(T,cap);n=read();
    for(int i=1;i<=n;++i) a[i].x=read(),a[i].y=read();
    m=read();
    for(int i=1;i<=m;++i){
        qq[i].op=read();if(qq[i].op==2) continue;
        qq[i].id=read();mk[qq[i].id]=1;
    }for(int i=1;i<=n;++i) if(!mk[i]) ins(a[i]);
    for(int i=m;i>=1;--i){
        if(qq[i].op==2) Ans.push_back(ans);
        else ins(a[qq[i].id]);
    }reverse(Ans.begin(),Ans.end());
    for(vector<double>::iterator it=Ans.begin();it!=Ans.end();++it)
        printf("%.2lf\n",*it);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/icefox_zhx/article/details/80878364