您的位置:首页 > 理论基础 > 计算机网络

HDU 5033 Building(2014北京网络赛 单调栈+几何)

2014-09-23 10:15 260 查看
博客原文地址:/article/2633962.html

Building

题目大意:有一排建筑物坐落在一条直线上,每个建筑物都有一定的高度,给出一个X坐标,高度为0,问X位置能看到的视角是多少度。如图:

图一:



图二:


图一为样例一,图二为样例三,红色部分为高楼,蓝色虚线为视角的最大范围。

解题思路:

由于有10w个点跟10w次询问,所以朴素的算法判断肯定会超时的。所以就需要用单调栈,维护相邻两建筑顶(xi,hi)的连线的斜率的绝对值上升的单调栈。

如图的单调栈存的大致走向

这样就可以做到O(n+m)的复杂度,再加上一个排序,也只有O((n+m)*log(n+m))的复杂度,就是完全可以接受的了。

具体的见代码部分:

#include <stdio.h>
#include <stack>
#include <math.h>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const double Pi = acos(-1.0);

struct Point {
    double x, y;
    int id;
} P[200005], Q[200005], L[200005], R[200005];

int dcmp(double x) {
    return x <-eps ? -1 : x > eps;
}
int cmp(Point a, Point b) {
    return a.x < b.x;
}
double xmult(Point a, Point b, Point c) {
    return (a.x-c.x)*(b.y-c.y) - (a.y-c.y)*(b.x-c.x);
}

double ans[200005];

int main()
{
    int n, m;
    int T, icase = 1;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for(int i = 0; i < n; ++i) {
            scanf("%lf%lf", &P[i].x, &P[i].y);
            P[i].id = -1;
        }
        scanf("%d", &m);
        for(int i = n; i < m+n; ++i) {
            scanf("%lf", &P[i].x);
            P[i].y = 0;
            P[i].id = i-n;
        }
        sort(P, P+n+m, cmp);

        int it = 0;
        for(int i = 0; i < n+m; ++i) {
            while(it >= 2 && dcmp(xmult(Q[it-1], Q[it-2], P[i])) <= 0) --it;
            if(it) L[i] = Q[it-1];
            Q[it++] = P[i];
        }
        it = 0;
        for(int i = n+m-1; i >= 0; --i) {
            while(it >= 2 && dcmp(xmult(Q[it-1], Q[it-2], P[i])) >= 0) --it;
            if(it) R[i] = Q[it-1];
            Q[it++] = P[i];
        }

        for(int i = 0; i < n; ++i) {
            if(P[i].id != -1) {
                ans[P[i].id] = atan((P[i].x-L[i].x)/L[i].y);
                ans[P[i].id] += atan((R[i].x-P[i].x)/R[i].y);
                ans[P[i].id] /= (Pi/180);
            }
        }
        printf("Case #%d:\n", icase++);
        for(int i = 0; i < m; ++i) {
            printf("%.16lf\n", ans[i]);
        }
    }

    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: