您的位置:首页 > 其它

bzoj2300: [HAOI2011]防线修建 计算几何 凸包

2015-02-26 23:24 393 查看
动态维护凸包。

由于只用管上凸部分,所以按x为第一关键字排序。

由于删点很麻烦,我们可以考虑离线加点。

这样就得把在凸包上的点建一个set

每次加点,如果点在凸包内那么直接返回。

如果在凸包外,就应该找到坐支和右支这样才能形成一个新的凸包。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
using namespace std;
#define pi acos(-1.0)
#define maxn 410000
#define eps 1e-10
double now,ans[200005];
int T,t1,t2,n,m,Q,b[200005];
bool mark[100005];
struct node
{
double x,y;
}p[maxn],del[maxn];
set<node>myset;
double sqr(double x)
{
return x*x;
}
double dis(node a,node b)
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
double operator * (node a,node b)
{
return a.x*b.y-a.y*b.x;
}
node operator - (node a,node b)
{
node t;
t.x=a.x-b.x; t.y=a.y-b.y;
return t;
}
node operator + (node a,node b)
{
node t;
t.x=a.x+b.x; t.y=a.y+b.y;
return t;
}
bool cmp(node a,node b)
{
if(fabs((a-p[1])*(b-p[1]))<eps)return dis(p[1],a)<dis(p[1],b);
return (a-p[1])*(b-p[1])>0;
}
bool operator<(node a,node b)
{
if(fabs(a.x-b.x)<eps) return a.y<b.y;
return a.x<b.x;
}
void insert(int a,int b)
{
node x=(node){a,b};
set<node>::iterator r=myset.lower_bound(x),l=r,t;
l--;
if((*r-*l)*(x-*l)<0) return;
now-=dis(*l,*r);
myset.insert(x);
while(l!=myset.begin())
{
t=l;l--;
if( (*t-x)*(*l-x)>0 ) break;
now-=dis(*t,*l);
myset.erase(t);
}
while(1)
{
t=r;r++;
if(r==myset.end())break;
if((*r-x)*(*t-x)>0)break;
now-=dis(*t,*r);
myset.erase(t);
}
myset.insert(x);
l=r=t=myset.find(x);
l--;r++;
now+=dis(*l,x)+dis(*r,x);
}
int main()
{
scanf("%d",&n);
myset.insert((node){0,0});
myset.insert((node){n,0});
node cap;
scanf("%lf%lf",&cap.x,&cap.y);
myset.insert(cap);
now+=dis((node){0,0},cap);
now+=dis((node){n,0},cap);
scanf("%d",&m);
for(int i=1;i<=m;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
int typ,x;
scanf("%d",&Q);
for(int i=1;i<=Q;i++)
{
scanf("%d",&typ);
if(typ==1)
{
scanf("%d",&x);
del[++t1]=p[x];
mark[x]=1;
}
else b[++t2]=t1;
}
for(int i=1;i<=m;i++) if(!mark[i])insert(p[i].x,p[i].y);
int T=t1;
for(int i=t2;i;i--)
{
while(T>b[i])
{
insert(del[T].x,del[T].y);
T--;
}
ans[i]=now;
}
for(int i=1;i<=t2;i++)printf("%.2lf\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: