• [LOJ 2022]「AHOI / HNOI2017」队长快跑


    [LOJ 2022]「AHOI / HNOI2017」队长快跑

    链接

    链接

    题解

    不难看出,除了影响到起点和终点的射线以外,射线的角度没有意义,因为如果一定要从该射线的射出一侧过去,必然会撞到射线

    因此,我们可以把射线的方向规约成两类,分成向上与向下的两种。

    不难发现,改变射线的方向后,原有的限制条件并未被改变。

    要判断一条线是否规约为“垂直向下”,只需判断它的关于P的极角是否在S和T关于P的极角之间。

    将所有射线按端点的横坐标排序,依次计算每个端点到S的最短路径上,距离它最近的点nxt。

    维护两个队列q1和q2,分别对应上和下两种方向的端点。

    初始时在q1和q2中都放入起点坐标。

    每次考虑到一个点P(不妨设它是向上的射线),首先看q2的队首到P的连线是否被队列中后一个元素挡住,如果是,则nxt在q2中;否则nxt在q1中。

    若nxt在q2中,则不断判断队首是否被后一个挡住,只要被挡住,就向后移动队首的指针,nxt就是最终的队首。

    接着,清空q1,并将nxt放入q1中。

    若nxt在q1中,则不断判断q1中倒数第二个是否被队尾挡住,只要没被挡住,就向前移动队尾的指针,nxt就是最终的队尾。

    最后,无论nxt在哪里,都在q1的末尾加入P。

    代码

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
     
    const int N = 1000009;
    const int LEN = 1e4;
    const double PI = acos(-1);
     
    int n,tot,st[N],head[2],tail[2];
    struct Point{
        LL x,y; Point *nxt; int pt;
        inline Point() {}
        inline Point(LL a, LL b):x(a),y(b) {}
        inline Point operator + (const Point &P) {return Point(x + P.x, y + P.y);}
        inline Point operator - (const Point &P) {return Point(x - P.x, y - P.y);}
        inline Point operator * (double t) {return Point(x * t, y * t);}
        inline LL operator ^ (const Point &P) {return x * P.x + y * P.y;}
        inline LL operator * (const Point &P) {return x * P.y - y * P.x;}
        inline bool operator < (const Point &P) const {return x < P.x;}
        inline bool operator != (const Point &P) const {return x != P.x || y != P.y;}
        inline double len() {return sqrt(x * x + y * y);}
    }ss,tt,p[N],vout[N],*que[2][N];
     
    inline int read() {
        char c=getchar(); int f=1,ret=0;
        while (c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
        while (c<='9'&&c>='0') {ret=ret*10+c-'0';c=getchar();}
        return ret * f;
    }
     
    inline bool NotInRange(double div, double a, double b) {
        if (div >= -PI / 2 && div <= PI / 2) return (a < div || a > PI / 2) && (b < div || b > PI / 2);
        else if (div < 0) return a > div && a < PI / 2 && b > div && b < PI / 2;
        else return (a > div || a < PI / 2) && (b > div || b < PI / 2);
    }
     
    int main() {
        n = read(); tt.x = read(); tt.y = read();
        for (int i=1;i<=n;i++) {
            p[i].x = read(); p[i].y = read();
            double r1,r2,r3; scanf("%lf",&r1);
            r2 = atan2((ss-p[i]).y, (ss-p[i]).x);
            r3 = atan2((tt-p[i]).y, (tt-p[i]).x);
            if (NotInRange(r1, r2, r3)) p[i].pt = 1; //射线朝上 
            else p[i].pt = 0; //射线朝下 
        }
        sort(p+1, p+1+n);
        int lim = n; n = 0;
        for (int i=1;i<=lim;i++) {
            if (p[i].x < ss.x || tt.x < p[i].x) continue;
            p[++n] = p[i];
        } 
        p[++n] = tt; 
        que[0][tail[0] = head[0] = 1] = &ss; 
        que[1][tail[1] = head[1] = 1] = &ss;
        for (int i=1;i<=n;i++) {
            int &h1 = head[p[i].pt], &h2 = head[p[i].pt ^ 1], &t1 = tail[p[i].pt], &t2 = tail[p[i].pt ^ 1];
            Point **a1 = que[p[i].pt], **a2 = que[p[i].pt ^ 1];
            if (h2 < t2 && ((p[i] - *a2[h2]) * (*a2[h2 + 1] - *a2[h2])) * (p[i].pt==1? 1: -1) >= 0) {
                while (h2 < t2 && ((p[i] - *a2[h2]) * (*a2[h2 + 1] - *a2[h2])) * (p[i].pt==1? 1: -1) >= 0) {
                    ++h2;
                }
                p[i].nxt = a2[h2];
                a1[h1 = t1 = t1 + 1] = a2[h2];
            } else {
                while (h1 < t1 && ((p[i] - *a1[t1 - 1]) * (*a1[t1] - *a1[t1 - 1])) * (p[i].pt==1? 1: -1) >= 0) {
                    --t1;
                }
                p[i].nxt = a1[t1];
            }
            a1[++t1] = &p[i];
        } 
        double ans = 0; 
        for (Point *cur=&p[n],*last;*cur!=ss;) {
            last = cur; cur = cur->nxt;
            ans += (*cur - *last).len(); 
        } 
        printf("%.10lf
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    CodeIgniter自定义配置文件
    js中opener和parent的区别
    更改Apache默认起始(索引)页面:DirectoryIndex
    基于知识管理的协同办公解决方案
    奥远新思创实用型办公自动化解决方案[1]
    OA与公文交换平台的接口解决方案
    金思维OA解决方案
    致力协同电力行业OA办公自动化解决方案[1]
    OA与公文交换平台的接口解决方案
    万户OA助力红豆集团信息化建设方案
  • 原文地址:https://www.cnblogs.com/wawawa8/p/10679175.html
Copyright © 2020-2023  润新知