P2521 [HAOI2011]防线修建

传送门

良心的动态凸包模板题

各种保证是真的舒服 $2333$

因为只有删除操作,所以直接倒过来变成插入就行了

上动态凸包,用 $set$ 把凸包的点按 $x,y$ 为一二关键字排序,然后加点的时候找找前驱后继看看要不要删,顺便维护当前凸包长度,没了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
using namespace std;
typedef long long ll;
typedef double db;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=4e5+7;
struct poi {
    db x,y;
    poi (db a=0,db b=0) { x=a,y=b; }
    inline poi operator - (const poi &tmp) const {
        return poi(x-tmp.x,y-tmp.y);
    }
    inline bool operator < (const poi &tmp) const {
        return x!=tmp.x ? x<tmp.x : y<tmp.y;
    }
}A[N],P[N],st[N];
inline db Cross(poi A,poi B) { return A.x*B.y-A.y*B.x; }
inline db Dot(poi A,poi B) { return A.x*B.x+A.y*B.y; }
inline db Len(poi A) { return sqrt(Dot(A,A)); }
inline bool cmp(const poi &A,const poi &B) { return (Cross(A,B)>0)||(Cross(A,B)==0&&Len(A)<Len(B)); }
int n,m,Q,tot,d[N][2];
bool vis[N];
db ans[N],now;
set <poi> S;
void Tubao()
{
    sort(P+1,P+tot+1,cmp); int Top=0;
    for(int i=1;i<=tot;st[++Top]=P[i],i++)
        while( Top>1 && Cross(P[i]-st[Top-1],st[Top]-st[Top-1])>=0 ) Top--;
    for(int i=3;i<=Top;i++) now+=Len(st[i]-st[i-1]); now+=Len(st[Top]-st[1]);
    for(int i=1;i<=Top;i++) S.insert(st[i]);
}
inline void Insert(poi A)
{
    set <poi>::iterator l=S.lower_bound(A),r=l,t;
    l--;
    if(Cross(A-(*l),(*r)-(*l))>0) return;
    now-=Len((*r)-(*l));
    while(r!=S.end())
    {
        t=r; r++; if(r==S.end()) break;
        if(Cross((*r)-A,(*t)-A)>0) break;
        now-=Len((*r)-(*t)); S.erase(t);
    }
    while(l!=S.begin())
    {
        t=l; l--;
        if(Cross((*l)-A,(*t)-A)<0) break;
        now-=Len((*l)-(*t)); S.erase(t);
    }
    S.insert(A); l=r=S.find(A);
    l--; r++;
    now+=Len(A-(*l))+Len(A-(*r));
}
int main()
{
    n=read(); int x=read(),y=read();
    m=read(); A[m+1]=poi(x,y); A[m+2]=poi(0,0); A[m+3]=poi(n,0);
    for(int i=1;i<=m;i++) A[i].x=read(),A[i].y=read();
    m+=3; Q=read();
    for(int i=1;i<=Q;i++)
    {
        d[i][0]=read();
        if(d[i][0]==1) d[i][1]=read(),vis[d[i][1]]=1;
    }
    for(int i=1;i<=m;i++) if(!vis[i]) P[++tot]=A[i];
    Tubao();
    for(int i=Q;i>=1;i--)
    {
        if(d[i][0]==2) ans[i]=now;
        else Insert(A[d[i][1]]);
    }
    for(int i=1;i<=Q;i++)
        if(d[i][0]==2) printf("%.2f\n",ans[i]);
    return 0;
}

 

posted @ 2019-09-06 16:00  LLTYYC  阅读(171)  评论(0编辑  收藏  举报