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

博客原文地址: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))的复杂度,就是完全可以接受的了。

具体的见代码部分:

#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;
}
时间: 2024-11-03 03:42:15

HDU 5033 Building(2014北京网络赛 单调栈+几何)的相关文章

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(北京网络赛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(北京网络赛)

Building                                                            Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 1090    Accepted Submission(s): 309 Special Judge Problem Description Once

hdu 5038 (2014北京网络赛G 排序水题)

题意:有n个数字,带入10000 - (100 - ai) ^ 2公式得到n个数,输出n个数中频率最大的数,如果有并列就按值从小到大都输出输出,如果频率相同的数字是全部的n个数,就输出Bad....题解:统计数字个数和频率,排序后输出. Sample Input36100 100 100 99 98 1016100 100 100 99 99 1016100 100 98 99 99 97 Sample OutputCase #1:10000Case #2:Bad MushroomCase #3

[2014 北京网络赛]

02 hdu 5033 Building 题目意思: 数轴上有n根柱子,每根柱子有个位置坐标和高度,有q个询问,询问从位置qi能看到的角度(保证左右至少有一个柱子) 解题思路: 单调栈维护一个凸性柱子序列. 离线处理所有的查询,排序,然后扫一遍qi,把柱子插进去,更新单调栈.注意查询位置也要更新栈. 代码: //#include<CSpreadSheet.h> #include<iostream> #include<cmath> #include<cstdio&g

[hdu 5032]2014北京网络赛Always Cook Mushroom 离散化+离线线段树/树状数组

Always Cook Mushroom Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 196    Accepted Submission(s): 54 Problem Description Matt has a company, Always Cook Mushroom (ACM), which produces high-q

HDU 5037 FROG 贪心 2014北京网络赛F

题目链接:点击打开链接 题意:有一条小河长为M的小河,可以看作一维轴,小河里存在N个石头,有一个每次能跳L米的小青蛙,随意添加石头保证青蛙能从头跳到尾的,问青蛙使用最优策略跳到对岸最多需要多少次. 思路:不妨假设青蛙每个石头都要经过一次,用step表示青蛙上一次跳的步长,每跳一次对目前点到下一点的距离和step的和与L做比较,如果小与,证明青蛙可以一次跳到这,更新step和青蛙位置,cnt保持不变,若大于,证明青蛙至少需要再跳一次,若lenth<=l,则直接跳,更新step=lenth,cnt+

HDU 5040 Instrusive(北京网络赛I题)

HDU 5040 Instrusive 题目链接 思路:记忆化广搜,先预处理出图,每个位置用一个二进制数表示,表示4秒为1个周期内,这个位置是否会被照到,然后进行记忆化广搜即可,状态多开一个4,表示在4秒一周期,然后进行转移即可 代码: #include <cstdio> #include <cstring> #include <queue> using namespace std; const int N = 505; const int d[4][2] = {-1,

HDU 5036 Explosion(北京网络赛E题)

HDU 5036 Explosion 题目链接 思路:对于每个点,只要考虑哪些炸掉能到他的个数cnt,那么他对应的期望就是1 / cnt,然后所以期望的和就是答案,用bitset来维护 代码: #include <cstdio> #include <cstring> #include <bitset> using namespace std; const int N = 1005; int t, n; bitset<N> bs[N]; int main()