[poj2451]Uyuw's Concert

半平面交滴裸题,但是要求nlogn,练练手

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm> 
#define MN 50000
#define eps 1e-17
#define ld long double
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

struct P
{
    ld x,y;
    P(ld _x=0,ld _y=0):x(_x),y(_y){}
    P operator +(P b){return P(x+b.x,y+b.y);}
    P operator -(P b){return P(x-b.x,y-b.y);}
    P operator *(ld b){return P(x*b,y*b);}
    ld operator^(P b){return x*b.y-b.x*y;}
}p[MN+5];
struct L
{
    P p,v;ld slop;
    L(){}
    L(P x,P y):p(x),v(y){slop=atan2(y.y,y.x);}
    P operator *(L y){P b=p-y.p;ld t=(y.v^b)/(v^y.v);return p+v*t;}
    bool operator <(const L&y)const{return slop<y.slop;}
    bool left(P y){return (v^(y-p))>eps;}
}q[MN+5],s[MN+5];
int n,top,tail;

void solve()
{
    q[top=tail=1]=s[1];
    for(int i=2;i<=n;i++)
    {
        while(top>tail&&!s[i].left(p[top])) --top;
        while(top>tail&&!s[i].left(p[tail+1])) ++tail;
        if(fabs(s[i].slop-q[top].slop)<eps)
            q[top]=s[i].left(q[top].p)?q[top]:s[i];
        else 
            q[++top]=s[i];
        p[top]=q[top]*q[top-1];
    }
    while(top>tail&&!q[tail].left(p[top])) --top; 
}

int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        double x,y,x2,y2;scanf("%lf%lf%lf%lf",&x,&y,&x2,&y2);
        s[i]=L(P(x,y),P(x2-x,y2-y));
    }
    s[++n]=L(P(0,0),P(10000,0));
    s[++n]=L(P(10000,0),P(0,10000));
    s[++n]=L(P(10000,10000),P(-10000,0));
    s[++n]=L(P(0,10000),P(0,-10000));
    sort(s+1,s+n+1);
    solve();p[tail]=q[top]*q[tail];
    if(top-tail<2) return 0*puts("0.0"); 
    ld ans=p[top]^p[tail];
    for(int i=tail;i<top;i++) ans+=p[i]^p[i+1];
    printf("%.1lf\n",(double)fabs(ans)/2.0);
    return 0;
}

 

转载于:https://www.cnblogs.com/FallDream/p/poj2451.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值