向天杰的动态凸包

还记得普通凸包里的那个while循环吗?我们现在只要把这个while循环给改一下,让每次新加入的点 按照极角序 往前 / 后遍历,我们就可以在平均复杂度 O(?) 的情况下求出来新的凸包。      我也不知道具体多少,但大多数情况下很快,至少不用遍历所有点

如果题目有额外要求,我们可以直接在插入函数里面进行维护,如本模板就是维护了新凸包的周长。

本模板其实并非插入点,而是删除点,大家可以自己好好体会。

关键是用set存点,然后找到前驱和后继结点,大家重点看Pre Nxt两个函数就好,其他的无非就是静态凸包的变形和set的应用

模板根据此题缩写 : 题目链接

#include
using namespace std;
#define ll long long
#define Pair pair
#define clean(a,b) memset(a,b,sizeof(a))// 水印
const int MAXN=1e5+10;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
struct Point {
	double x,y,vis,l;
	Point(double _x=0,double _y=0,double _vis=0,double _l=0) {
		x=_x;
		y=_y;
		vis=_vis;
		l=_l;
	}
	friend Point operator + (const Point &a,const Point &b) {
		return Point(a.x+b.x,a.y+b.y);
	}
	friend Point operator - (const Point &a,const Point &b) {
		return Point(a.x-b.x,a.y-b.y);
	}
	friend double operator ^ (Point a,Point b) { //向量叉乘
		return a.x*b.y-a.y*b.x;
	}
	friend bool operator == (const Point &a,const Point &b) {
		if(fabs(a.x-b.x) Set;
Pair q[MAXN];
int vis[MAXN];
double ans[MAXN],ansl;
double dis(Point a,Point b) {
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool operator < (Point a,Point b) {
	a=a-Basic;
	b=b-Basic;
	double Ang1=atan2(a.y,a.x),Ang2=atan2(b.y,b.x);
	double Len1=dis(a,Point(0,0)),Len2=dis(b,Point(0,0));
	if(fabs(Ang1-Ang2)::iterator Pre(set::iterator it) {//set中it的前驱结点 
	if(it==Set.begin()) it=Set.end();
	return --it;
}
set::iterator Nxt(set::iterator it) {//set中it的后继结点
	++it;
	return it==Set.end()?Set.begin():it;
}
int Query(Point p) {//查询点是否在凸包内 
	set::iterator it=Set.lower_bound(p);
	if(it==Set.end()) it=Set.begin();
	return ((p- *(Pre(it)))^(*(it)-*(Pre(it))))::iterator it;
	it=Set.find(p); 
	ansl-=dis(*(Nxt(it)),*(Pre(it)));//维护本题的答案,即凸包周长,下面的ansl的处理,与此同理 
	ansl+=dis(*(it),*(Pre(it)));
	ansl+=dis(*(it),*(Nxt(it)));
	it=Pre(Set.find(p));
	while(Set.size()>3&&((p- *(it))^(*(it)- *(Pre(it))))>-EPS) {//按照极角序往前遍历,极端情况下遍历之前几乎所有点 
		ansl-=dis(*(it),*(Nxt(it)));
		ansl-=dis(*(it),*(Pre(it)));
		ansl+=dis(*(Nxt(it)),*(Pre(it)));
		Set.erase(it);
		it=Pre(Set.find(p));
	}
	it=Nxt(Set.find(p));
	while(Set.size()>3&&((p- *(Nxt(it)))^(*(it)- *(Nxt(it))))=1; --i) {
		if(q[i].first==2) {
			ans[k++]=ansl;
		} else {
			Insert(Dots[q[i].second]);
		}
	}
	for(int i=k-1; i>=0; --i) {
		printf("%.2lf\n",ans[i]);
	}
	return 0;
}

 

你可能感兴趣的:(向天杰的动态凸包)