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

来源:互联网 发布:人工智能的未来 pdf 编辑:程序博客网 时间:2024/06/14 06:28

博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/39494433


Building


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

图一:  

图二:


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


解题思路:

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

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

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


人当做h=0的楼处理

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int MAXN = 200005;const double pi = acos(-1.0);struct Build{    Build() {        memset(ang, 0, sizeof(ang));     }    double x, h;        double ang[2];    bool pos;    int id; }b[MAXN], q[MAXN];int t, n, m;bool cmp1(Build a, Build b) {    return a.x < b.x;}bool cmp2(Build a, Build b) {    return a.id < b.id;}double deal(Build a, Build b) {    double dx = fabs(b.x - a.x);    double dy = b.h - a.h;     return dy / dx;}int main() {    int cas, t = 1;    scanf("%d", &cas);     while (cas--) {        scanf("%d", &n);        for (int i = 0; i < n; i++) {            scanf("%lf%lf", &b[i].x, &b[i].h);             b[i].pos = false;            b[i].id = i;        }         scanf("%d", &m);         for (int i = n; i < n + m; i++) {            scanf("%lf", &b[i].x);              b[i].h = 0;             b[i].pos = true;            b[i].id = i;        }           n += m;        sort(b, b + n, cmp1);        q[0] = b[0];                int top = 0;        for (int i = 1; i < n; i++) {            if (b[i].pos == false) {                while (top && deal(b[i], q[top]) < deal(q[top], q[top - 1]))                      top--;                q[++top] = b[i];            }            else {                int tmp = top;                 while (tmp && deal(b[i], q[tmp]) < deal(b[i], q[tmp - 1]))                      tmp--;                b[i].ang[0] = deal(b[i], q[tmp]);            }         }        q[0] = b[n - 1];        top = 0;        for (int i = n - 2; i >= 0; i--) {            if (b[i].pos == false) {                while (top && deal(b[i], q[top]) < deal(q[top], q[top - 1]))                      top--;                q[++top] = b[i];            }            else {                int tmp = top;                 while (tmp && deal(b[i], q[tmp]) < deal(b[i], q[tmp - 1]))                      tmp--;                b[i].ang[1] = deal(b[i], q[tmp]);            }          }                printf("Case #%d:\n", t++);        sort(b, b + n, cmp2);                for (int i = 0; i < n; i++) {            if (b[i].pos == true) {                double ans = pi - atan(b[i].ang[0]) - atan(b[i].ang[1]);                 ans = ans / pi * 180;                printf("%.4lf\n", ans);             }          }    }    return 0;}




原创粉丝点击