bzoj 2300: [HAOI2011]防线修建 凸包

题目大意:

http://www.lydsy.com/JudgeOnline/problem.php?id=2300

题解

这道题让我们维护一个支持动态删除点的上凸壳
并且告诉了我们三个一定不会被删除的点
也就是说,无论什么时候这都是一个凸包
如果我们考虑从凸包里删除一个点吗...这个点在凸包里还好说,不用管了
在凸包上嘛...哪位dalao写出来了请教教我,并不会删除QAQ
所以我们倒序考虑所有的操作,将其变成动态插入点
每一次插入一个点的时候,我们找到凸包上与这个点关联的两个点
(按照横纵坐标进行双关键字排序后与之相邻的两个点)
我们就从这两个点开始依次向左右拓展,并且即时更新凸包的长度
所以我们用set存一下所有在凸包上的点即可

#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
    x=0;char ch;bool flag = false;
    while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 100010;
const int maxm = 200010;
struct Point{
    int x,y;
    Point(const int &a = 0,const int &b = 0){x=a;y=b;}
    void print(){
        printf("Point : (%d,%d)\n",x,y);
    }
};
typedef Point Vector;
Vector operator + (const Vector &a,const Vector &b){
    return Vector(a.x+b.x,a.y+b.y);
}
Vector operator - (const Vector &a,const Vector &b){
    return Vector(a.x-b.x,a.y-b.y);
}
bool operator < (const Point &a,const Point &b){
    return a.x == b.x ? a.y < b.y : a.x < b.x;
}
int operator * (const Vector &a,const Vector &b){
    return a.x*b.x + a.y*b.y;
}
inline int cross(const Vector &a,const Vector &b){
    return a.x*b.y - a.y*b.x;
}
inline double sqr(const double &x){
    return x*x;
}
inline double dis(Point a,Point b){
    return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
}
struct Node{
    int cmd,x;
}quer[maxm];
set<Point>s;
Point p[maxn];bool vis[maxn];
double ans = .0;
double anss[maxm];int cnt;
void insert(Point x){
    set<Point>::iterator r = s.lower_bound(x);
    set<Point>::iterator l = --r;r++;
    set<Point>::iterator it;
    if(cross(x - *l,*r - *l) >= 0) return;
    ans -= dis(*l,*r);
    while(1){
        it = r++;
        if(r == s.end()) break;
        if(cross(*r - *it,*it - x) > 0) break;
        ans -= dis(*it,*r);s.erase(it);
    }
    ans += dis(x,*it);
    while(1){
        it = l--;
        if(it == s.begin()) break;
        if(cross(x - *it,*it - *l) > 0) break;
        ans -= dis(*it,*l);s.erase(it);
    }
    ans += dis(x,*(it));
    s.insert(x);
}
int main(){
    int n,x,y;read(n);read(x);read(y);
    s.insert(Point(0,0));
    s.insert(Point(x,y));
    s.insert(Point(n,0));
    ans += dis(Point(0,0),Point(x,y)) + dis(Point(x,y),Point(n,0));
    read(n);
    for(int i=1;i<=n;++i){
        read(p[i].x);
        read(p[i].y);
    }
    int m;read(m);
    for(int i=1;i<=m;++i){
        read(quer[i].cmd);
        if(quer[i].cmd == 1){
            read(quer[i].x);
            vis[quer[i].x] = true;
        }
    }
    for(int i=1;i<=n;++i){
        if(!vis[i]) insert(p[i]);
    }
    for(int i=m;i>=1;--i){
        if(quer[i].cmd == 1) insert(p[quer[i].x]);
        else anss[++cnt] = ans;
    }
    for(int i=cnt;i>=1;--i) printf("%.2lf\n",anss[i]);
    getchar();getchar();
    return 0;
}
posted @ 2017-02-23 21:23  Sky_miner  阅读(242)  评论(0编辑  收藏  举报