「BZOJ2300」[HAOI2011] 防线修建

传送门

操作离线之后倒着做,只有加点操作。

用set动态维护凸包即可。

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=100007;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,q,cnt,no[N],qs[N][2],top;
db ans,res[N];

template<typename T>void read(T &x)  {
    char ch=getchar(); x=0; T f=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

struct pt {
    int x,y;
    pt(){}
    pt(int x,int y):x(x),y(y){}
    friend bool operator <(const pt&A,const pt&B) {
        return A.x<B.x||(A.x==B.x&&A.y<B.y);
    }
}p[N],a[N],h[N];
set<pt>s;

pt operator - (const pt&A,const pt&B) { return pt(A.x-B.x,A.y-B.y); } 

int cross(pt A,pt B) { return A.x*B.y-A.y*B.x; }
LL dot(pt A,pt B) { return (LL)A.x*B.x+A.y*B.y; }
db length(pt A) { return sqrt(dot(A,A)); }

void make_ham(int n) {
    sort(a+2,a+n+1);
    h[++top]=a[1]; h[++top]=a[2];
    For(i,3,n) {
        while(top>1&&cross(h[top]-h[top-1],a[i]-h[top-1])>=0) top--;
        h[++top]=a[i]; 
    }
    For(i,1,top) {
        s.insert(h[i]);
        if(i>1) ans+=length(h[i]-h[i-1]);
    } 
}

#define IT set<pt>::iterator
void insert(int id) {
    pt x=p[id];
    IT l=s.lower_bound(x);
    IT r=l,t; --l;
    if(cross(x-*l,*r-*l)>=0) return;
    ans-=length(*l-*r);
    while(1) {
        t=r; r++; if(r==s.end()) break;
        if(cross(*t-x,*r-x)>=0) {
            ans-=length(*t-*r); s.erase(t);
        }
        else break;
    }
    while(1) {
        if(l==s.begin()) break;
        t=l; l--;
        if(cross(*t-*l,x-*l)>=0) {
             ans-=length(*t-*l); s.erase(t); 
        }
        else break;
    }    
    s.insert(x);  
    l=r=s.find(x); 
    --l; ++r;
    ans+=length(*l-x)+length(*r-x);
}

#define DEBUG
int main() {
#ifdef DEBUG
    freopen("2300.in","r",stdin);
    freopen("2300.out","w",stdout);
#endif
    read(n); read(p[0].x); read(p[0].y);
    read(m);
    For(i,1,m) { read(p[i].x); read(p[i].y); }
    read(q);
    For(i,1,q) {
        read(qs[i][0]);
        if(qs[i][0]==1) {
            read(qs[i][1]);
            no[qs[i][1]]=1;
        }
    }
    a[++cnt]=pt(0,0); a[++cnt]=pt(n,0);
    For(i,0,m) if(!no[i]) a[++cnt]=p[i];
    make_ham(cnt);
    Rep(i,q,1) {
        int o=qs[i][0],x=qs[i][1];
        if(o==2) res[i]=ans;
        else insert(x);
    }
    For(i,1,q) if(qs[i][0]==2) printf("%.2lf\n",res[i]);
    return 0;
}
View Code

 

posted @ 2018-03-26 15:37  啊宸  阅读(153)  评论(0编辑  收藏  举报