HDU5033-Building(维护单调栈)

题目链接

题意:给出n座大楼的位置以及高度,再给出m个人的位置,查询给出的人的位置所能看到的最大的仰角是多少。

思路:维护每两座的楼之间的斜率,使之成为一个凸面,用栈来维护,听了GG小伙伴的思路,可以将人当作高度为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;
}

时间: 2024-10-07 14:21:34

HDU5033-Building(维护单调栈)的相关文章

hdu5033 Building (单调栈+)

http://acm.hdu.edu.cn/showproblem.php?pid=5033 2014 ACM/ICPC Asia Regional Beijing Online B 1002 Building Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 0    Accepted Submission(s): 0Special

HDU 5033 Building (维护单调栈)

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

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 排序.. 从左往右扫,单调栈维护斜率小的.. 从右往左扫,单调栈维护斜率大的.. #inc

玲珑杯”ACM比赛 Round #19 B 维护单调栈

1149 - Buildings Time Limit:2s Memory Limit:128MByte Submissions:588Solved:151 DESCRIPTION There are nn buildings lined up, and the height of the ii-th house is hihi. An inteval [l,r][l,r](l≤r)(l≤r) is harmonious if and only if max(hl,…,hr)−min(hl,…,

HDU 5033 Building --离线+单调栈

题意:给一些建筑物,x表示横坐标,h表示高度,然后查询某些坐标x,问从该点看向天空的最大张角是多大. 解法:离线操作,读入所有数据,然后按x升序排序,对每一个查询的x,先从左到右,依次添加x坐标小于x的建筑物,加入一个建筑物的条件: 1.此建筑物高度大于栈中的前一个,这个必然是最优的. 2.加入这个建筑物后不能使相对斜率: stk[top-2]~stk[top-1] 比a[j]~stk[top-1]大(负数),即出现凹形,否则会出现这种: 如图,即中间那个根本没用了,加入第三根的时候就要判一下.

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

浅谈—单调栈

一.概念: 单调栈的本质还是一个栈,只不过是栈的元素从栈底到栈顶单调递增或者是单调递减. 二.单调栈的维护: 每加入一个元素,将这个元素和栈顶元素相比较,(假设你维护的是一个单调递增的栈),如果当前元素大于等于栈顶元素,说明这个元素 没有破坏这个栈的单调性,直接加入:如果当前元素小于栈顶元素,直接向栈中加入元素会破坏栈的单调性,这时我们需要将栈顶元素依次弹出,知道遇到第一个 大于或者等于当前元素的元素,再将该元素压入栈中.时间复杂度O(n),所有的元素都会进栈一次. 三.单调栈的性质: (1)单

【AtCoder】ARC067 F - Yakiniku Restaurants 单调栈+矩阵差分

[题目]F - Yakiniku Restaurants [题意]给定n和m,有n个饭店和m张票,给出Ai表示从饭店i到i+1的距离,给出矩阵B(i,j)表示在第i家饭店使用票j的收益,求任选起点和终点的最大(收益-代价).n<=5000,m<=200. [算法]单调栈+矩阵差分 [题解]直接枚举区间,很难同时计算m张票,我们反过来考虑每个B(i,j)的贡献. 对于B(i,j),令x为满足x<i,B(x,j)>B(i,j)的最大的x,令y为满足y>i,B(y,j)>B(

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