• [9018]1630: 离大海最远点在哪里?


    9018传说级神题,精度要求只有,嗯,17位……跟老师交流后加上了SPJ,绝对误差小于1e-6或相对误差小于1e-8可过,总算是道能做的题了。

    题目大意:给定一个n个点的凸多边形,求形内一点到边上最小距离最大,求出这个距离。(n<=200,000,坐标绝对值<=10^11,保留6位小数)

    思路:容易想到二分答案,把边向内推然后半平面交check,复杂度O(nlogAns),看上去很科学实际上常数巨大无比,以至于在POJ上这题的n是100,而且这么做精度差也比较大。正解是用双向链表+堆维护这些边,模拟把边向内推进,先把所有边放进双向链表中,我们维护一条边什么时候会被相邻的两条边取代,容易发现是这条边到他与相邻两边的角平分线的交点的距离,用堆维护这个距离,每次把最小的那条边删掉,直到删到只剩两条边即可知道答案,复杂度O(nlogn)。

    #include<cstdio>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define ll long long
    #define lb long double
    inline ll read()
    {
        ll x,f=1;char c;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=0;
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return f?x:-x;
    }
    #define MN 200000
    struct point{lb x,y;point(lb x=0,lb y=0):x(x),y(y){}}p[MN+5];
    point operator+(point a,point b){return point(a.x+b.x,a.y+b.y);}
    point operator-(point a,point b){return point(a.x-b.x,a.y-b.y);}
    point operator*(point a,lb b){return point(a.x*b,a.y*b);}
    lb operator*(point a,point b){return a.x*b.y-a.y*b.x;}
    lb length(point p){return sqrt(p.x*p.x+p.y*p.y);}
    struct line{point p,v;}l[MN+5];
    point operator*(line a,line b){return a.p+a.v*(b.v*(a.p-b.p)/(a.v*b.v));}
    line ab(line a,line b){return (line){a*b,b.v*length(a.v)-a.v*length(b.v)};}
    priority_queue<pair<lb,int> > pq;
    int ls[MN+5],nx[MN+5],u[MN+5];
    lb cal(int x){return -fabs(l[x].v*(ab(l[ls[x]],l[x])*ab(l[x],l[nx[x]])-l[x].p)/length(l[x].v));}
    int main()
    {
        int n=read(),i,j;
        for(i=0;i<n;++i)p[i].x=read(),p[i].y=read();
        for(p[n]=p[i=0];i<n;++i)l[i].p=p[i],l[i].v=p[i+1]-p[i];
        for(i=0;i<n;++i)ls[i]=i-1,nx[i]=i+1;nx[ls[0]=n-1]=0;
        for(i=0;i<n;++i)pq.push(make_pair(cal(i),i));
        for(i=3;i<n;++i)
        {
            for(u[j=pq.top().second]=1;u[pq.top().second];)pq.pop();
            nx[ls[j]]=nx[j];ls[nx[j]]=ls[j];
            pq.push(make_pair(cal(ls[j]),ls[j]));
            pq.push(make_pair(cal(nx[j]),nx[j]));
        }
        printf("%.6lf",-(double)pq.top().first);
    }
  • 相关阅读:
    scp命令
    遇到的错误解决方法
    阿里云挂载数据盘
    正则表达式
    python例子三
    Linux shell快捷键
    《超级产品的本质:汽车大王亨利福特自传》书评
    学习嵌入式的一点建议【转】
    win7使用USB转串口连接mini2440方法
    吐血原创:mini2440和win7笔记本利用无路由功能的交换机共享上网(使用x-router软路由)
  • 原文地址:https://www.cnblogs.com/ditoly/p/9018-1630.html
Copyright © 2020-2023  润新知