SGU 277 Heroes(动态凸包维护)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=277

题意:维护一个凸包,每次加一个点。输出每次加入后的凸包面积。

思路:如下图,找到内部一点,以每个点对这个点的极角建立set。每次查找left和right,然后将中间的点删掉,增加p。修改面积。

SGU 277 Heroes(动态凸包维护)

#include <iostream>

#include <cstdio>

#include <string.h>

#include <algorithm>

#include <cmath>

#include <vector>

#include <queue>

#include <set>

#include <stack>

#include <string>

#include <map>





#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define abs(x) ((x)>=0?(x):-(x))

#define i64 long long

#define u32 unsigned int

#define u64 unsigned long long

#define clr(x,y) memset(x,y,sizeof(x))

#define CLR(x) x.clear()

#define ph(x) push(x)

#define pb(x) push_back(x)

#define Len(x) x.length()

#define SZ(x) x.size()

#define PI acos(-1.0)

#define sqr(x) ((x)*(x))

#define MP(x,y) make_pair(x,y)



#define FOR0(i,x) for(i=0;i<x;i++)

#define FOR1(i,x) for(i=1;i<=x;i++)

#define FOR(i,a,b) for(i=a;i<=b;i++)

#define DOW0(i,x) for(i=x;i>=0;i--)

#define DOW1(i,x) for(i=x;i>=1;i--)

#define DOW(i,a,b) for(i=a;i>=b;i--)

using namespace std;





void RD(int &x){scanf("%d",&x);}

void RD(i64 &x){scanf("%I64d",&x);}

void RD(u32 &x){scanf("%u",&x);}

void RD(double &x){scanf("%lf",&x);}

void RD(int &x,int &y){scanf("%d%d",&x,&y);}

void RD(i64 &x,i64 &y){scanf("%I64d%I64d",&x,&y);}

void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}

void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}

void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}

void RD(i64 &x,i64 &y,i64 &z){scanf("%I64d%I64d%I64d",&x,&y,&z);}

void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}

void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}

void RD(char &x){x=getchar();}

void RD(char *s){scanf("%s",s);}

void RD(string &s){cin>>s;}





void PR(int x) {printf("%d\n",x);}

void PR(i64 x) {printf("%I64d\n",x);}

void PR(u32 x) {printf("%u\n",x);}

void PR(u64 x) {printf("%llu\n",x);}

void PR(double x) {printf("%.3lf\n",x);}

void PR(char x) {printf("%c\n",x);}

void PR(char *x) {printf("%s\n",x);}

void PR(string x) {cout<<x<<endl;}



int DB(double x)

{

    if(x>1e-10) return 1;

    if(x<-1e-10) return -1;

    return 0;

}



class point

{

public:

    i64 x,y;

    double ang;



    point(){}

    point(i64 _x,i64 _y)

    {

        x=_x;

        y=_y;

    }



    void read()

    {

        RD(x,y);

    }

    int operator<(const point &a) const

    {

        return DB(ang-a.ang)<0;

    }



    point operator-(point a)

    {

        return point(x-a.x,y-a.y);

    }



    i64 operator*(point a)

    {

        return x*a.y-y*a.x;

    }

};



set<point> p;

vector<point> q;

double X,Y;

int n,isTrangle;

point a;

i64 s;





i64 cross(point a,point b,point p)

{

    return (b-a)*(p-a);

}



int cmp(point a,point b)

{

    if(a.x!=b.x) return a.x<b.x;

    return a.y<b.y;

}



double getAng(point a)

{

    return atan2(a.y-Y,a.x-X);

}



void init()

{

    X=(q[0].x+q[1].x+q[2].x)/3.0;

    Y=(q[0].y+q[1].y+q[2].y)/3.0;

    int i;

    q[3]=q[0];

    FOR0(i,3)

    {

        q[i].ang=getAng(q[i]);

        p.insert(q[i]);

        s+=q[i]*q[i+1];

    }

    s=abs(s);

}





#define type set<point>::iterator



type last(type it)

{

    if(it==p.begin()) it=p.end();

    return --it;

}



type next(type it)

{

    if(++it==p.end()) it=p.begin();

    return it;

}



void update(point a)

{

    type it=last(p.lower_bound(a));

    point b=*it,x,y;

    if(cross(b,*next(it),a)>0) return;

    type L=it,R=it;

    while(cross(a,*next(R),*R)>=0) R=next(R);

    while(cross(a,*L,*last(L))>=0) L=last(L);

    for(it=L;it!=R;it=next(it))

    {

        x=*it;

        y=*next(it);

        s-=x*y;

    }

    for(it=next(L);it!=R;)

    {

        it=next(it);

        p.erase(last(it));

    }

    x=*L;y=*R;

    s+=x*a+a*y;

    p.insert(a);

}



int main()

{

    a.read(); q.pb(a);

    a.read(); q.pb(a);

    a.read(); q.pb(a);

    if(cross(q[0],q[1],q[2])) isTrangle=1,init();

    RD(n);

    while(n--)

    {

        a.read();

        if(isTrangle) a.ang=getAng(a),update(a);

        else if(cross(q[0],q[1],a))

        {

            isTrangle=1;

            sort(q.begin(),q.end(),cmp);

            q[1]=q[q.size()-1];

            q[2]=a;

            init();

        }

        else q.pb(a);

        PR(s);

    }

    return 0;

}

  

你可能感兴趣的:(动态)