BZOJ 2300凸包+离线

思路:

倒着加显然吧  动态维护这个凸包就好了

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=200050;
int n,m,q,vis[N];
double now;
struct Point{int x,y;}point[N],jy,tmp,tt;
struct Query{int x,op;double ans;}ask[N];
Point operator-(Point a,Point b){
    Point c;c.x=a.x-b.x,c.y=a.y-b.y;return c;
}
int operator*(Point a,Point b){
    return a.x*b.y-a.y*b.x;
}
bool operator<(Point a,Point b){
    if(a.x!=b.x)return a.x<b.x;
    return a.y<b.y;
}
double dis(Point a,Point b){
    a=a-b;return sqrt(a.x*a.x+a.y*a.y);
}
set<Point>s;set<Point>::iterator l,r,t;
void insert(Point a){
    r=s.lower_bound(a),l=r,l--;
    if((*r-*l)*(a-*l)<0)return;
    now-=dis((*l),(*r));
    s.insert(a),t=r,r++;
    while(r!=s.end()&&(*r-a)*(*t-a)<0)
        now-=dis(*t,*r),s.erase(t),t=r,r++;
    while(l!=s.begin()){
        t=l,l--;
        if((*t-a)*(*l-a)>0)break;
        now-=dis(*t,*l),s.erase(t);
    }
    l=r=t=s.find(a),l--,r++;
    now+=dis(*l,a)+dis(*r,a);
}
int main(){
    s.insert(tt);
    scanf("%d%d%d%d",&n,&jy.x,&jy.y,&m);
    tmp.x=n;now+=dis(tt,jy)+dis(jy,tmp);
    for(int i=1;i<=m;i++)
        scanf("%d%d",&point[i].x,&point[i].y);
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        scanf("%d",&ask[i].op);
        if(ask[i].op==1)scanf("%d",&ask[i].x),vis[ask[i].x]=1;
    }s.insert(jy),s.insert(tmp);
    for(int i=1;i<=m;i++)if(!vis[i])insert(point[i]);
    for(int i=q;i;i--){
        if(ask[i].op==1)insert(point[ask[i].x]); 
        else ask[i].ans=now;
    }
    for(int i=1;i<=q;i++)
        if(ask[i].op!=1)printf("%.2lf\n",ask[i].ans);
}

 

posted @ 2017-05-26 15:37  SiriusRen  阅读(178)  评论(0编辑  收藏  举报