标签: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