您的位置:首页 > 产品设计 > UI/UE

HDU 5033 Building (单调栈)

2014-09-25 21:34 281 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5033

题意:给你n栋楼,每栋楼有高度和坐标,现在给你q个询问,问你人站在某个位置,能看到的天空的最大角度

思路:将询问的人和楼组合在一起,排序后,维护单调栈使得图形为凸的,然后每次查询到人的位置的时候,都维护单调栈,那么栈首和这个人就能构成答案了,还有是楼的时候也要维护这个栈,那么前后各遍历一次,就能通过数学正切角求解了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>

typedef long long ll;
using namespace std;

const double PI = acos(-1.0);
const int maxn = 200100;
const int inf = 1e8;

struct Node
{
int x, h;
bool operator <(const Node &a)const
{
return x < a.x;
}
} node[maxn], stk[maxn];

double ans[maxn];
int n, q;

int check(Node a, Node b, Node c)
{
if (c.h <= 0)
c.h = 0;
return (ll)(a.h - c.h) * (c.x - b.x) >= (ll)(b.h - c.h) * (c.x - a.x);
}

double ang(Node a, Node b)
{
return atan(1.0 * (b.x - a.x) / a.h);
}

void solve()
{
int head = 0;
for (int i = 0; i < n + q; i++)
{
if (node[i].h <= 0)
{
while (head >= 2 && check(stk[head - 2], stk[head - 1], node[i]))
head--;
ans[-node[i].h] += ang(stk[head - 1], node[i]);
}
else
{
while (head && stk[head - 1].h <= node[i].h)
head--;
while (head >= 2 && check(stk[head - 2], stk[head - 1], node[i]))
head--;
stk[head++] = node[i];
}
}
}

int main()
{
int t, cas = 1;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d%d", &node[i].x, &node[i].h);
scanf("%d", &q);
for (int i = 0; i < q; i++)
{
scanf("%d", &node[i + n].x);
node[i + n].h = -i;
}
memset(ans, 0, sizeof(ans));
sort(node, node + n + q);
solve();
reverse(node, node + n + q);
for (int i = 0; i < n + q; i++)
node[i].x = inf - node[i].x;
solve();
printf("Case #%d:\n", cas++);
for (int i = 0; i < q; i++)
printf("%.10lf\n", ans[i] * 180.0 / PI);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: