题意:
给出一个点集,每次可能删去一个点或查询上凸包的面积;
保证无重点,保证最左面 最右面的点一定在凸包上;
n<=100000,m<=200000;
题解:
动态凸包问题,然而这道题的保证简直极为良心;
所以呢,我们就可以用set来水这道题啦;
我还是涨了不少姿势的,比如迭代器居然可以自减;
离线所有的操作之后处理,就是凸包加点了;
每次来一个点,判断一下加不加入,之后左面干点右面干点,插进去就好了;
不过这题细节还是用很多,主要是边界问题吧;
时间复杂度O(set(n))O(nlogn);
代码:
#include<set>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110000
#define iter set<Point>::iterator
using namespace std;
const double INF=1e100;
struct Point
{
int x,y;
Point(){}
Point(int _,int __):x(_),y(__){}
friend bool operator <(Point a,Point b)
{
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
friend bool operator ==(Point a,Point b)
{
return a.x==b.x&&a.y==b.y;
}
friend bool slope (Point a,Point b,Point c)
{
double s1=a.x==b.x?(a.y<b.y?INF:-INF):(a.y-b.y)*1.0/(a.x-b.x);
double s2=b.x==c.x?(b.y<c.y?INF:-INF):(b.y-c.y)*1.0/(b.x-c.x);
return s1<s2;
}
friend double dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+0.0);
}
}a[N],p;
int Qx[N<<1],top;
bool Q[N<<1],ban[N];
double st[N<<1];
set<Point>s;
int main()
{
int n,m,q,i,j,k;
double ans;
scanf("%d%d%d",&n,&p.x,&p.y);
s.insert(p),s.insert(Point(0,0)),s.insert(Point(n,0));
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
}
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d",&k);
if(k==1)
{
Q[i]=1;
scanf("%d",Qx+i);
ban[Qx[i]]=1;
}
}
ans=dis(p,Point(0,0))+dis(p,Point(n,0));
for(i=1;i<=m;i++)
{
if(!ban[i])
{
iter it1=s.insert(a[i]).first;
iter it2=it1,temp=it1;
it1++,it2--;
if(slope(*it2,a[i],*it1))
{s.erase(temp);continue;}
if(*it1==Point(n,0)&&*it2==Point(0,0))
ans=0;
else
ans-=dis(*it1,*it2);
temp=it1;
while(++temp!=s.end()&&slope(a[i],*it1,*temp))
ans-=dis(*it1,*temp),s.erase(it1++);
temp=it2;
while(temp--!=s.begin()&&slope(*temp,*it2,a[i]))
ans-=dis(*it2,*temp),s.erase(it2--);
ans+=dis(a[i],*it1)+dis(a[i],*it2);
}
}
for(i=q;i>=1;i--)
{
if(Q[i])
{
iter it1=s.insert(a[Qx[i]]).first;
iter it2=it1,temp=it1;
it1++,it2--;
if(slope(*it2,a[Qx[i]],*it1))
{s.erase(temp);continue;}
if(*it1==Point(n,0)&&*it2==Point(0,0))
ans=0;
else
ans-=dis(*it1,*it2);
temp=it1;
while(++temp!=s.end()&&slope(a[Qx[i]],*it1,*temp))
ans-=dis(*it1,*temp),s.erase(it1++);
temp=it2;
while(temp--!=s.begin()&&slope(*temp,*it2,a[Qx[i]]))
ans-=dis(*it2,*temp),s.erase(it2--);
ans+=dis(a[Qx[i]],*it1)+dis(a[Qx[i]],*it2);
}
else
st[++top]=ans;
}
while(top)
{
printf("%.2lf\n",st[top--]);
}
}
原文地址:http://blog.csdn.net/ww140142/article/details/48824451