动态凸包,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");
}
}
}