hdu - 5033 - Building(单调栈)

题意:N 幢楼排成一列(1<=N<=10^5),各楼有横坐标 xi(1<=xi<=10^7) 以及高度 hi(1<=hi<=10^7),在各楼之间的Q个位置(1<=Q<=10^5),问这些位置可以仰望天空的夹角是多少度。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5033

——>>将楼和人的位置一起按 x 排序。。

从左往右扫,单调栈维护斜率小的。。

从右往左扫,单调栈维护斜率大的。。

#include <cstdio>
#include <algorithm>
#include <cmath>

using std::sort;

const double EPS = 1e-8;
const double PI = acos(-1.0);
const int MAXN = 100000 + 10;

int N, Q, kase;
double L[MAXN], R[MAXN];

int Dcmp(double x)
{
    if (fabs(x) < EPS) return 0;
    return x > 0 ? 1 : -1;
}

struct BUILD
{
    double x;
    double h;
    int id;

    bool operator < (const BUILD& e) const
    {
        return Dcmp(x - e.x) < 0;
    }
} b[MAXN << 1];

double Slope(const BUILD& a, const BUILD& b)
{
    return (b.h - a.h) / (b.x - a.x);
}

int st[MAXN];
struct MS
{
    int top;

    MS(): top(0) {}

    void Push(int id)
    {
        st[top++] = id;
    }

    void PopMax(const BUILD* b, const int& id)
    {
        while (top >= 2 && Dcmp(Slope(b[id], b[st[top - 1]]) - Slope(b[id], b[st[top - 2]])) >= 0)
        {
            --top;
        }
    }

    void PopMin(const BUILD* b, const int& id)
    {
        while (top >= 2 && Dcmp(Slope(b[id], b[st[top - 1]]) - Slope(b[id], b[st[top - 2]])) <= 0)
        {
            --top;
        }
    }

    int Top()
    {
        return st[top - 1];
    }
};

void Read()
{
    scanf("%d", &N);
    for (int i = 1; i <= N; ++i)
    {
        scanf("%lf%lf", &b[i].x, &b[i].h);
        b[i].id = 0;
    }
    scanf("%d", &Q);
    for (int i = 1; i <= Q; ++i)
    {
        scanf("%lf", &b[i + N].x);
        b[i + N].id = i;
        b[i + N].h = 0.0;
    }
}

void Init()
{
    sort(b + 1, b + 1 + N + Q);
}

void GetLeft()
{
    MS ms;

    for (int i = 1; i <= N + Q; ++i)
    {
        if (!b[i].id)
        {
            ms.PopMax(b, i);
            ms.Push(i);
        }
        else
        {
            ms.PopMax(b, i);
            int j = ms.Top();
            L[b[i].id] = b[j].h / (b[i].x - b[j].x);
        }
    }
}

void GetRight()
{
    MS ms;

    for (int i = N + Q; i >= 1; --i)
    {
        if (!b[i].id)
        {
            ms.PopMin(b, i);
            ms.Push(i);
        }
        else
        {
            ms.PopMin(b, i);
            int j = ms.Top();
            R[b[i].id] = b[j].h / (b[j].x - b[i].x);
        }
    }
}

void Output()
{
    printf("Case #%d:\n", ++kase);
    for (int i = 1; i <= Q; ++i)
    {
        printf("%.10f\n", 180.0 / PI * (PI - atan(L[i]) - atan(R[i])));
    }
}

int main()
{
    int T;

    kase = 0;
    scanf("%d", &T);
    while (T--)
    {
        Read();
        Init();
        GetLeft();
        GetRight();
        Output();
    }

    return 0;
}
时间: 2024-10-12 20:22:27

hdu - 5033 - Building(单调栈)的相关文章

hdu 5033 Building (单调栈 或 暴力枚举 )

Description Once upon a time Matt went to a small town. The town was so small and narrow that he can regard the town as a pivot. There were some skyscrapers in the town, each located at position x i with its height h i. All skyscrapers located in dif

HDU - 5033 Building (单调栈+倍增)

题意:有一排建筑,每座建筑有一定的高度,宽度可以忽略,求在某点的平地上能看到天空的最大角度. 网上的做法基本都是离线的...其实这道题是可以在线做的. 对于向右能看到的最大角度,从右往左倍增维护每个时刻的单调栈(凸壳),对于每个询问,先二分找到它右面的第一个建筑的位置,然后在对应的凸壳上倍增找到切点即可. 向左看把x坐标对称一下就行. 复杂度$O(nlogn)$ 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long lo

HDU 5033 Building(北京网络赛B题)

HDU 5033 Building 题目链接 思路:利用单调栈维护建筑建的斜线,保持斜率单调性,然后可以把查询当成高度为0的建筑,和建筑和在一起考虑,从左往右和从右往左各扫一遍即可 代码: #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <algorithm> using namespace std; const int N = 200

hdu 5033 Building(单调性+二分)

题目链接:hdu 5033 Building 题目大意:城市里有n座摩天大厦,给定每栋大厦的位置和高度,假定大厦的宽度为0.现在有q次查询,表示人站的位置,人的高度视为0,问说可以仰望天空的角度. 解题思路:比赛的时候用单调性优化直接给过了,对于每个大厦来说,记录左右两边与其形成斜率最大的大厦序号以及斜率,然后每次查询是,通过二分确认人所在位置属于哪两栋大厦之间,然后分别向左向右确认角度,在确认角度时,根据大厦记录的最大斜率进行判断. 以左边为例, 然后对于查询位置x: 这种解法仅仅是优化查询效

Hdu 4923(单调栈)

题目链接 Room and Moor Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 842    Accepted Submission(s): 250 Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is eit

HDU 5033 Building(北京网络赛B题) 单调栈 找规律

做了三天,,,终于a了... 11724203 2014-09-25 09:37:44 Accepted 5033 781MS 7400K 4751 B G++ czy Building Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 1257    Accepted Submission(s): 358 Special Judg

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

博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/39494433 Building 题目大意:有一排建筑物坐落在一条直线上,每个建筑物都有一定的高度,给出一个X坐标,高度为0,问X位置能看到的视角是多少度.如图: 图一: 图二: 图一为样例一,图二为样例三,红色部分为高楼,蓝色虚线为视角的最大范围. 解题思路: 由于有10w个点跟10w次询问,所以朴素的算法判断肯定会超时的.所以就需要用单调栈,维护相邻两建筑顶(xi,hi)的

HDU 5033 Building (维护单调栈)

题目链接 题意:n个建筑物,Q条询问,问所在的位置,看到天空的角度是多少,每条询问的位置左右必定是有建筑物的. 思路 : 维护一个单调栈,将所有的建筑物和所有的人都放到一起开始算就行,每加入一个人,就维护栈里的建筑物的高度,也就是说这个人所能够看到的建筑物时在栈里的,但是这个人看不到的就删掉,例如下图,中间三个点可以删掉了,因为角度问题中间三个是看不到的,所以不会影响最终求得角度 还有一种情况,就是下述的情况,不停的维护单调栈,人站在不同的地方角度也是不一样的. 维护的是相邻两建筑顶(xi,hi

Largest Rectangle in a Histogram HDU - 1506 (单调栈)

A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the