Codeforces 70D Professor's task [动态凸包]

来源:互联网 发布:淘宝超级运动会是什么 编辑:程序博客网 时间:2024/05/16 15:19

题意:初始给你三个点,之后有若干操作

①加入一个点,使点集成为一个新的凸包

②判断一个点是否在凸包中

题解:对点进行极角排序(用set维护),判断点是否在凸包内时,查找该点的前驱和后继,判断叉积即可。对于加入的点的操作,我们需要将点插入set用判断凸包的方法,从该点出发,对其左右进行判断。

AC代码:

#include<stdio.h>#include<set>#include<math.h>using namespace std;typedef long long ll;struct point{ll x,y;ll len;double ang;point(){}point(ll x,ll y){this->x=x;this->y=y;}}o,a[5];ll q;set<point>st;set<point>::iterator qian,hou,it;bool operator<(point a,point b){if(a.ang==b.ang)return a.len<b.len;return a.ang<b.ang;}point operator-(point A,point B)  //点-点=向量{return point(A.x-B.x,A.y-B.y);}ll Cross(point A,point B)           //叉积 {return A.x*B.y-A.y*B.x;}set<point>::iterator L(set<point>::iterator x){if(x == st.begin()) x = st.end();      x--;      return x; }set<point>::iterator R(set<point>::iterator x) {      x++;      if(x == st.end()) x = st.begin();      return x;  } int main(){scanf("%lld",&q);ll op;for(ll i=0;i<3;i++){scanf("%lld%lld%lld",&op,&a[i].x,&a[i].y);o.x+=a[i].x;o.y+=a[i].y;a[i].x*=3;a[i].y*=3;}for(ll i=0;i<3;i++){a[i].len=(ll)(a[i].y-o.y)*(a[i].y-o.y)+(ll)(a[i].x-o.x)*(a[i].x-o.x);a[i].ang=atan2(a[i].y-o.y,a[i].x-o.x);st.insert(a[i]);}q-=3;while(q--){ll x,y;scanf("%lld%lld%lld",&op,&x,&y);x*=3,y*=3;point p=point(x,y);p.len=(ll)(y-o.y)*(y-o.y)+(ll)(x-o.x)*(x-o.x);p.ang=atan2(y-o.y,x-o.x);hou=st.lower_bound(p);if(hou==st.end())hou=st.begin();qian=L(hou);if(op==1){if(Cross(p-*qian,*hou-p)<=0)continue;st.insert(p);        set<point>::iterator cur,i,j;        cur=st.find(p);i=L(cur);j=L(i);        while(Cross(*j-*cur,*i-*j) <= 0) {              st.erase(i);            i=j;j=L(j);}        i=R(cur);j=R(i);        while(Cross(*j-*cur,*i-*j) >= 0) {            st.erase(i);            i=j;j=R(i);        }}else {if(Cross(p-*qian,*hou-p)<=0)printf("YES\n");else printf("NO\n");}} }


原创粉丝点击