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;
} 
posted @ 2020-01-09 17:13  nofind  阅读(147)  评论(0编辑  收藏  举报