动态凸包(询问点是否在凸包内部)

动态凸包,n次操作,添加一个点,或询问一个点是否在凸包内部.
ps:询问每次更新后的凸包面积的板子在Hdu板子上.

typedef long long ll;
const int MOD = 1e9 + 7;
const int INF = 0x7fffffff;
const double eps = 1e-9;

const int N = 1e5 + 50,M = 1e5 + 50;

#define MP make_pair
typedef pair<int,int>PII;
map<int,int>convex[2];
map<int,int>::iterator p,q,it,it1,it2;

ll Cross(PII a,PII b,PII c) {
	return 1ll*(b.fi-a.fi)*(c.se-a.se)-1ll*(b.se-a.se)*(c.fi-a.fi);
}


//点是否在凸包内部
bool judge(map<int,int>&st,int x,int y) {
	if(!st.size())return false;
	if(st.find(x)!=st.end())return y>=st[x];
	if(x<st.begin()->fi || (--st.end())->fi < x)return false;
	p = st.lower_bound(x);
	q = p,q--;	//找到左右点
	return Cross(MP(x,y),*q,*p)>=0;
}


void insert(map<int,int>&st,int x,int y) {
	if(judge(st,x,y))return ;
	st[x] = y;
	p = st.upper_bound(x);
	it = p,it--;
	it1 = it,it1--;
	it2 = it1,it2--;
	if(p != st.end()) {
		q = p,q++;
		while(q != st.end() && Cross(MP(x,y),*q,*p)>=0) {
			st.erase(p);
			p = q,q ++;
		}
	}
	if(it == st.begin() || it1 == st.begin())return ;
	while(it1 != st.begin() && Cross(MP(x,y),*it1,*it2)>=0) {
		st.erase(it1),it1=it2,it2--;
	}
}

int n;

void work() {
	scanf("%d",&n);
	while(n--) {
		int op,x,y;
		scanf("%d%d%d",&op,&x,&y);
		if(op == 1) {
			insert(convex[0],x,y);
			insert(convex[1],x,-y);
		} else {
			bool ans1=judge(convex[0],x,y);
			bool ans2=judge(convex[1],x,-y);
			if(ans1&&ans2)puts("YES");
			else puts("NO");
		}
	}
}
原文地址:https://www.cnblogs.com/LaiYiC/p/15073241.html