标签:operator 注意 point iterator scan -o class std opera
题意:给三个点和一些操作,可以加点或询问某点是否在当前点集的凸包内
如果写水平序凸包,要维护上下凸壳,挺麻烦
注意到题目给了初始的三个点,所以直接在这个三角形里面随便找一个点(我选的是重心)作为原点,然后做极角序凸包就可以了
#include<stdio.h> #include<math.h> #include<set> using namespace std; const double pi=3.141592653589793238462643383; const double eps=1e-8; double abs(double x){return x>0?x:-x;} struct point{ double xx,yy,ang,len; point(double x=0.,double y=0.){ xx=x; yy=y; len=sqrt(x*x+y*y); if(abs(x)<eps) ang=y>eps?pi*.5:pi*-.5; else{ if(x>eps) ang=atan(y/x); else ang=(y>eps?pi:-pi)+atan(y/x); } } }p; point operator-(point a,point b){ return point(a.xx-b.xx,a.yy-b.yy); } double operator*(point a,point b){ return a.xx*b.yy-a.yy*b.xx; } bool operator<(point a,point b){ if(a.ang==b.ang)return a.len<b.len; return a.ang<b.ang; } set<point>s; typedef set<point>::iterator sit; sit it; sit nex(sit x){ x++; return x==s.end()?s.begin():x; } sit pre(sit x){ if(x==s.begin())x=s.end(); x--; return x; } int main(){ int q,i,op,x[3],y[3]; double ox,oy,xx,yy; scanf("%d",&q); q-=3; ox=oy=0; for(i=0;i<3;i++){ scanf("%d%d%d",&op,x+i,y+i); ox+=x[i]; oy+=y[i]; } ox/=3.; oy/=3.; for(i=0;i<3;i++)s.insert(point(x[i]-ox,y[i]-oy)); while(q--){ scanf("%d%d%d",&op,x,y); xx=x[0]-ox; yy=y[0]-oy; p=point(xx,yy); it=s.lower_bound(p); if(it==s.end())it=s.begin(); if(op==1){ if((p-*pre(it))*(*it-p)>eps){ s.insert(p); it=nex(s.find(p)); while(s.size()>3&&(*it-p)*(*nex(it)-*it)<eps){ s.erase(it); it=nex(s.find(p)); } it=pre(s.find(p)); while(s.size()>3&&(*it-*pre(it))*(p-*it)<eps){ s.erase(it); it=pre(s.find(p)); } } }else puts((p-*pre(it))*(*it-p)<eps?"YES":"NO"); } }
标签:operator 注意 point iterator scan -o class std opera
原文地址:http://www.cnblogs.com/jefflyy/p/7894363.html