HDU 5033 (单调栈维护凸包) Building

题意:

一个人在x轴上,他的左右两侧都有高楼,给出楼的横坐标Xi和高度Hi还有人的位置pos,求人所能看到的天空的最大角度。

分析:

将建筑物和人的位置从左到右排序,对于每个位置利用栈求一次人左边建筑物的凸包,找到一个最小的角度,然后对称一下,再找一个右边的建筑物的最小角度,两个角度加起来就是答案。

将人左边的建筑物从左到右扫描,下面两种情况会出栈:

  1. 栈顶元素楼高小于等于当前扫描到的楼高,因此这是一个单调的栈
  2. 栈顶两个楼顶所在直线的斜率 小于 栈顶的楼顶和当前楼顶所在直线的斜率(这里的斜率指的是绝对值),这保证了栈中所有楼顶的构成的曲线是个凸包

然后再求人的视线和竖直线的最小角度时,如果栈顶的楼的人的视线与水平线夹角 大于 栈中第二个楼所成的夹角,则出栈

代码中用到了STL里的pair,pair相当于有两个元素first 和 second的结构体,所定义的小于是判断容器x是否小于y。该操作先判断x.first < y.first的关系,然后再判断x.second < y.second的关系。所以特别需要注意的是:T1和T2必须支持“<”操作符,否则编译报错。

虽然没有图,可是如果理解了的话,心中自有图。=_=||

 1 //#define LOCAL
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6
 7 const double pi = acos(-1.0);
 8 const int maxn = 100000 + 10;
 9
10 pair<double, double> p[maxn];
11 pair<double, int> pos[maxn];
12 double ans[maxn];
13 int stack[maxn], n, Q;
14
15 double slope(const int a, const int b)
16 {
17     return -(p[a].second - p[b].second) / (p[a].first - p[b].first);
18 }
19
20 double angle(const int a, const int b)
21 {
22     return atan((pos[b].first - p[a].first) / p[a].second);
23 }
24
25 void solve()
26 {
27     int j = 0, top = 0;
28     for(int i = 0; i < Q; ++i)
29     {
30         while(j < n && p[j].first < pos[i].first)
31         {
32             while(top > 0 && p[stack[top]].second <= p[j].second)   top--;
33             while(top >= 2 && slope(stack[top], j) < slope(stack[top - 1], stack[top])) top--;
34             stack[++top] = j;
35             j++;
36         }
37         while(top >= 2 && angle(stack[top], i) > angle(stack[top - 1], i))    top--;
38         ans[pos[i].second] += angle(stack[top], i);
39     }
40 }
41
42 int main()
43 {
44     #ifdef LOCAL
45         freopen("5033in.txt", "r", stdin);
46     #endif
47
48     int T, kase;
49     scanf("%d", &T);
50     for(int kase = 1; kase <= T; ++kase)
51     {
52         scanf("%d", &n);
53         for(int i = 0; i < n; ++i)
54             scanf("%lf%lf", &p[i].first, &p[i].second);
55         sort(p, p + n);
56
57         scanf("%d", &Q);
58         for(int i = 0; i < Q; ++i)
59         {
60             scanf("%lf", &pos[i].first);
61             pos[i].second = i;
62             ans[i] = 0.0;
63         }
64         sort(pos, pos + Q);
65         solve();
66
67         reverse(p, p + n);
68         reverse(pos, pos + Q);
69         for(int i = 0; i < n; ++i)  p[i].first = -p[i].first;
70         for(int i = 0; i < Q; ++i)  pos[i].first = -pos[i].first;
71         solve();
72
73         printf("Case #%d:\n", kase);
74         for(int i = 0; i < Q; ++i)
75             printf("%.10lf\n", ans[i]/pi*180.0);
76     }
77
78     return 0;
79 }

代码君

时间: 2024-10-10 22:05:00

HDU 5033 (单调栈维护凸包) Building的相关文章

hdu 5033 单调栈 ****

看出来是单调栈维护斜率,但是不会写,2333,原来是和询问放在一起的 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <cmath> 7 typedef __int64 ll; 8 using namespace std; 9 10 const doub

Lost My Music:倍增实现可持久化单调栈维护凸包

题目就是求树上每个节点的所有祖先中(ci-cj)/(dj-di)的最小值. 那么就是(ci-cj)/(di-dj)的最大值了. 对于每一个点,它的(ci,di)都是二维坐标系里的一个点 要求的就是祖先节点的所有点与目前节点连线的最小斜率 比较容易想到单调栈优化,像斜率优化dp一样 但是关键是本题在树上,会有很多麻烦的操作. 当搜到某一个儿子时可能会弹很多栈,而回溯的过程中需要把它们加回来. 如果暴力执行的话,会在蒲公英图退化为n2. 考虑优化:现在的关键就是在于在一个元素可能被弹栈/还原多次的情

CF1137E Train Car Selection(单调栈维护凸函数)

首先本题的关键是一次性加0操作只有第一个0是有用的.然后对于1 k操作,其实就是把之前的所有数删除.对于其他的情况,维护一次函数的和,将(i,a[i])看成平面上的一个点,用单调栈维护一下. #include<bits/stdc++.h> using namespace std; const int N=3e5+7; #define int long long typedef pair<int,int>pii; int n,k,b,Q,top; pii st[N]; long do

HDU 5033---Building(单调栈)

题目链接 Problem 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 xi with its height hi. All skyscrapers loc

hdu 1506 单调栈问题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1506 题目的意思其实就是要找到一个尽可能大的矩形来完全覆盖这个矩形下的所有柱子,只能覆盖柱子,不能留空. 我们求得的面积其实就是Max{s=(right[i] - left[i] + 1)*height[i];(i>=1&&i<=n)} 每一个柱子都要尽可能向左向右延伸,使得获得最大的面积. 此时我就要用到单调栈 单调栈就是栈内元素单调递增或者单调递减的栈,单调栈只能在栈顶操作.

hdu 5875(单调栈)

Function Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1866    Accepted Submission(s): 674 Problem Description The shorter, the simpler. With this problem, you should be convinced of this tr

POJ2796---Feel Good(前缀和+单调栈维护)

Description Bill is developing a new mathematical theory for human emotions. His recent investigations are dedicated to studying how good or bad days influent people's memories about some period of life. A new idea Bill has recently developed assigns

【单调栈维护连续区间】2019.1.18模拟赛T2 浇花

这道题是一道单调栈的题 1 题目描述 2 JDFZ在餐厅门前种了一排nn棵花,每棵花都有一个高度.浇花大爷会枚举所有的区间,然后从区间中找出一个高度最矮的花进行浇水.由于浇花大爷浇完水之后就精疲力竭了,所以请你帮助他计算每棵花都被浇了几次水. 3 4 输入格式 5 第一行一个整数nn. 第二行nn个整数,分别表示每棵花的高度. 6 7 输出格式 8 一行nn个整数用空格隔开,分别表示每棵花被浇了几次水. 9 10 样例一 11 input 12 3 13 1 3 5 14 output 15 3

hdu 3410 单调栈

http://acm.hdu.edu.cn/showproblem.php?pid=3410 Passing the Message Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 827    Accepted Submission(s): 546 Problem Description What a sunny day! Let's