BZOJ 2300 [HAOI2011]防线修建 ——计算几何

只需要倒着插入,然后维护一个凸包就可以了。

可以用来学习set的用法

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define inf 100000
#define ll long long
#define mp make_pair
#define sqr(x) x*x
 
int n,x,y,m,k;
struct Vector{
    double x,y;
    void print(){printf("Vector (%.3f,%.3f)\n",x,y);}
};
 
struct Point{
    int x,y;
    void print(){printf("Point (%d,%d)\n",x,y);}
    bool operator < (const Point b) const{
        return x==b.x?y<b.y:x<b.x;
    }
}a[200005];
 
set <Point> s;
 
struct Options{int opt,id;}q[200005];
 
double dist (Point a,Point b)
{
//  printf("dist\n");
//  a.print();b.print();
//  printf("The ans is %.6f\n",sqr((double)a.x-b.x)+sqr((double)a.y-b.y));
    return sqrt(((double)a.x-b.x)*((double)a.x-b.x)+((double)a.y-b.y)*((double)a.y-b.y));
}
 
Vector operator - (Point a,Point b)
{Vector ret;ret.x=a.x-b.x;ret.y=a.y-b.y;return ret;}
 
double operator * (Vector a,Vector b)
{
//  a.print(); printf("* * *\n");
//  b.print();
//  printf("= %.6f\n",a.x*b.y-a.y*b.x);
    return a.x*b.y-a.y*b.x;
}
 
int tot,del[200005];
double ans[200005],now;
Point newnode;
 
void init()
{
    now=n*1.0;
    newnode.x=0;newnode.y=0;
    s.insert(newnode);
//  newnode.x=0;newnode.y=-inf;
//  s.insert(newnode);
    newnode.x=n;newnode.y=0;
    s.insert(newnode);
//  newnode.x=n;newnode.y=-inf;
//  s.insert(newnode);
//  printf("now is %.6f\n",now);
}
 
void add(Point x)
{
//  printf("Add "); x.print();
    set<Point>::iterator it,iL,iR;
    it=s.lower_bound(x);
    iL=it;iL--;iR=it;
    if ((x-*iL)*(*iR-x)>0) return;
//  printf("New node\n");
    now-=dist(*iL,*iR);
    for (;;)
    {
        iR=it;it++;
        if (it==s.end()) break;
        if ((*iR-x)*(*it-x)>0)
        {
            now-=dist(*iR,*it);
            s.erase(*iR);
//          printf("del R\n"); while (1);
        }
        else break;
    }
    for (;;)
    {
        if (iL==s.begin()) break;
        Point L=*iL; iL--;
//      (*iL-*it).print();
//      (*it-x).print();
        if ((L-*iL)*(x-*iL)>0)
        {
            now-=dist(*iL,L);
            s.erase(L);
//          printf("del L\n"); //while(1);
        }
        else break;
    }
    s.insert(x);
    it=s.find(x);
    iL=it;iL--;iR=it;iR++;
    now+=dist(*iL,x)+dist(x,*iR);
//  printf("now is %.6f\n",now);
    return ;
}
 
void Finout()
{
    freopen("defense.in","r",stdin);
    freopen("defense.out","w",stdout);
}
 
int main()
{
//  freopen("in.txt","r",stdin);
    scanf("%d%d%d",&n,&x,&y);
    scanf("%d",&m);
    F(i,1,m) scanf("%d%d",&a[i].x,&a[i].y);
    scanf("%d",&k);
//  printf("k is %d\n",k);
    F(i,1,k)
    {
        scanf("%d",&q[i].opt);
        switch(q[i].opt)
        {
            case 1:scanf("%d",&q[i].id); del[q[i].id]=1;break;
            case 2:q[i].id=++tot; break;
        }
    }
//  F(i,1,k) printf("Opt %d id %d\n",q[i].opt,q[i].id);
    init(); newnode.x=x;newnode.y=y;add(newnode);
    F(i,1,m) if (!del[i]) add(a[i]);
    D(i,k,1)
    {
        switch(q[i].opt)
        {
            case 1:add(a[q[i].id]);break;
            case 2:ans[q[i].id]=now;break;
        }
    }
    F(i,1,tot) printf("%.2f\n",ans[i]);
}

  

posted @ 2017-04-09 20:11  SfailSth  阅读(152)  评论(0编辑  收藏  举报