bzoj 1249: SGU277 HERO
题意
这是极角序维护凸包。
找一个点作为基准点,我选的是\(p1\)和\(p_2,p_3\)的中点的中点。
用\(set\)维护凸包,内部按照极角排序。
插入一个点:
如果之前存在就不插入。
不然就找到它的前驱\(pre\)和后继\(nxt\),之后不断弹掉两边的点,中途维护下面积即可。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100010;
const double eps=1e-8;
int n,cnt=3;
ll ans;
struct Point
{
double x,y;
inline double len(){return x*x+y*y;}
Point operator+(const Point& a)const{return (Point){x+a.x,y+a.y};}
Point operator-(const Point& a)const{return (Point){x-a.x,y-a.y};}
Point operator*(const double& k){return (Point){x*k,y*k};}
Point operator/(const double& k){return (Point){x/k,y/k};}
double operator*(const Point& a)const{return x*a.y-y*a.x;}
double operator&(const Point& a)const{return x*a.x+y*a.y;}
};
Point st;
Point p[5];
inline int dcmp(double x)
{
if(fabs(x)<=eps)return 0;
return x<0?-1:1;
}
bool operator<(Point a,Point b)
{
Point tmpa=a-st,tmpb=b-st;
if(dcmp(tmpa.y*tmpb.y)<0)return dcmp(tmpa.y-tmpb.y)<0;
if(!dcmp(tmpa.y)&&!dcmp(tmpb.y)&&dcmp(tmpa.x*tmpb.x)<0)return dcmp(tmpa.x-tmpb.x)<0;
double det=tmpa*tmpb;
if(dcmp(det)!=-0)return dcmp(det)>0;
return dcmp(a.len()-b.len())>0;
}
set<Point>s;
inline Point getpre(Point a)
{
set<Point>::iterator it=s.find(a);
if(it==s.begin())it=s.end();
return *(--it);
}
inline Point getnxt(Point a)
{
set<Point>::iterator it=s.find(a);
if((++it)==s.end())it=s.begin();
return *it;
}
inline ll calc(Point a,Point b)
{
a=a-p[1],b=b-p[1];
return abs((ll)a.x*(ll)b.y-(ll)a.y*(ll)b.x);
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
for(int i=1;i<=3;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
st=(p[1]+(p[2]+p[3])*0.5)*0.5;
ans=calc(p[2],p[3]);
for(int i=1;i<=3;i++)s.insert(p[i]);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
Point a;scanf("%lf%lf",&a.x,&a.y);
if(s.count(a)){printf("%lld\n",ans);continue;}
s.insert(a);
Point pre=getpre(a),nxt=getnxt(a);
if(dcmp((a-pre)*(nxt-a))<0)
{
s.erase(a);
printf("%lld\n",ans);
continue;
}
cnt++;
ans-=calc(pre,nxt);
Point b=getpre(pre);
while(cnt>3&&dcmp((pre-b)*(a-pre))<=0)
{
ans-=calc(b,pre);
s.erase(pre);cnt--;
pre=b,b=getpre(pre);
}
b=getnxt(nxt);
while(cnt>3&&dcmp((nxt-a)*(b-nxt))<=0)
{
ans-=calc(nxt,b);
s.erase(nxt);cnt--;
nxt=b,b=getnxt(nxt);
}
ans+=calc(pre,a)+calc(a,nxt);
printf("%lld\n",ans);
}
return 0;
}