hdu 5033 Building(斜率优化)

Building

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)

Total Submission(s): 1237    Accepted Submission(s): 350

Special Judge

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 located in different place. The skyscrapers had no width, to make it simple. As the skyscrapers were so high, Matt could hardly see the sky.Given the position Matt was at, he wanted to know how large the angle range was where he could see the sky.
Assume that Matt‘s height is 0. It‘s guaranteed that for each query, there is at least one building on both Matt‘s left and right, and no building locate at his position.

Input

The first line of the input contains an integer T, denoting the number of testcases. Then T test cases follow.

Each test case begins with a number N(1<=N<=10^5), the number of buildings.

In the following N lines, each line contains two numbers, xi(1<=xi<=10^7) and hi(1<=hi<=10^7).

After that, there‘s a number Q(1<=Q<=10^5) for the number of queries.

In the following Q lines, each line contains one number qi, which is the position Matt was at.

Output

For each test case, first output one line "Case #x:", where x is the case number (starting from 1).

Then for each query, you should output the angle range Matt could see the sky in degrees. The relative error of the answer should be no more than 10^(-4).

Sample Input

3
3
1 2
2 1
5 1
1
4
3
1 3
2 2
5 1
1
4
3
1 4
2 3
5 1
1
4

Sample Output

Case #1:
101.3099324740
Case #2:
90.0000000000
Case #3:
78.6900675260

Source

2014 ACM/ICPC Asia Regional Beijing Online

Recommend

hujie   |   We have carefully selected several similar problems for you:  5041 5040 5039 5038 5037

题意:

告诉你n(1e5)个建筑物的位置和高度。现在q(1e5)条询问。每次询问如果你站在x处。问你所能看到天空的角度。

x.y都为浮点数。

思路:

用单调队列维护一个上凸曲线。因为下凸曲线的凸点是不可能成为答案的。这个画画图就明白了。找答案时队列中答案之后建筑物都可以去掉了。因为都没有答案建筑物优。然后从左到右算一次。然后从右往左算一次。就可以算出每个询问的角度了。

详细见代码:

#include<algorithm>
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<math.h>
using namespace std;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
const int maxn=100010;
typedef long long ll;
struct node
{
    double x,y;
} bd[maxn],q[maxn],qu[maxn],le[maxn],ri[maxn];
int head,tail;
bool cmp(node a,node b)
{
    return a.x<b.x;
}
double ans[maxn];
int main()
{
    int t,cas=1,n,m,i,j,p;
    double x1,y1,x2,y2,per=180/PI;

    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=0;i<n;i++)
            scanf("%lf%lf",&bd[i].x,&bd[i].y);
        sort(bd,bd+n,cmp);
        scanf("%d",&m);
        for(i=0;i<m;i++)
            scanf("%lf",&qu[i].x),qu[i].y=i;
        sort(qu,qu+m,cmp);
        head=tail=j=0;
        for(i=0;i<m;i++)
        {
            for(;j<n&&bd[j].x<qu[i].x;j++)
            {
                while(tail-head>0&&bd[j].y>=q[tail-1].y)
                    tail--;
                while(tail-head>=2)
                {
                    p=tail-1;
                    x2=bd[j].x-q[p].x;
                    y2=bd[j].y-q[p].y;
                    x1=q[p].x-q[p-1].x;
                    y1=q[p].y-q[p-1].y;
                    if(x1*y2>=x2*y1)
                        tail--;
                    else
                        break;
                }
                q[tail].x=bd[j].x;
                q[tail++].y=bd[j].y;
            }
            if(tail-head==0)
                le[i].x=qu[i].x-1,le[i].y=0;
            else
            {
                while(tail-head>=2)
                {
                    p=tail-1;
                    x2=qu[i].x-q[p].x;
                    y2=-q[p].y;
                    x1=qu[i].x-q[p-1].x;
                    y1=-q[p-1].y;
                    if(x2*y1<=x1*y2)
                        tail--;
                    else
                        break;
                }
                le[i].x=q[tail-1].x;
                le[i].y=q[tail-1].y;
            }
        }
        head=tail=0,j=n-1;
        for(i=m-1;i>=0;i--)
        {
            for(;j>=0&&bd[j].x>qu[i].x;j--)
            {
                while(tail-head>0&&bd[j].y>=q[tail-1].y)
                    tail--;
                while(tail-head>=2)
                {
                    p=tail-1;
                    x2=bd[j].x-q[p].x;
                    y2=bd[j].y-q[p].y;
                    x1=q[p].x-q[p-1].x;
                    y1=q[p].y-q[p-1].y;
                    if(x2*y1>=x1*y2)
                        tail--;
                    else
                        break;
                }
                q[tail].x=bd[j].x;
                q[tail++].y=bd[j].y;
            }
            if(tail-head==0)
                ri[i].x=qu[i].x+1,ri[i].y=0;
            else
            {
                while(tail-head>=2)
                {
                    p=tail-1;
                    x2=qu[i].x-q[p].x;
                    y2=-q[p].y;
                    x1=qu[i].x-q[p-1].x;
                    y1=-q[p-1].y;
                    if(x1*y2<=x2*y1)
                        tail--;
                    else
                        break;
                }
                ri[i].x=q[tail-1].x;
                ri[i].y=q[tail-1].y;
            }
        }
        for(i=0;i<m;i++)
        {
            x1=le[i].x-qu[i].x;
            y1=le[i].y;
            x2=ri[i].x-qu[i].x;
            y2=ri[i].y;
            ans[int(qu[i].y)]=per*acos((x1*x2+y1*y2)/(sqrt(x1*x1+y1*y1)*sqrt(x2*x2+y2*y2)));
        }
        printf("Case #%d:\n",cas++);
        for(i=0;i<m;i++)
            printf("%.10f\n",ans[i]);
    }
    return 0;
}
时间: 2024-07-30 03:11:36

hdu 5033 Building(斜率优化)的相关文章

hdu 5033 Building(单调性+二分)

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

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

Print Article hdu 3507 一道斜率优化DP 表示是基础题,但对我来说很难

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 4990    Accepted Submission(s): 1509 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique

hdu 3507(DP+斜率优化)

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 6653    Accepted Submission(s): 2054 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique

HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)

题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小.一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0. 析:DP状态方程很容易想出来,dp[i][j] 表示前 j 个数分成 i 组.但是复杂度是三次方的,肯定会超时,就要对其进行优化. 有两种方式,一种是斜率对其进行优化,是一个很简单的斜率优化 dp[i][j] = min{dp[i-1][k] - w[k] + sum[k]*sum[k] - sum[k]*sum[

HDU 5033 Building

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5033 解题报告:在一条x轴上有n个建筑物,每个建筑物有一个高度h,然后现在有q次查询,查询的内容是假设有一个人站在xi这个位置,问他看天空的视角是多大,用角度表示. 数据量都比较大,n和q都是10^5,但因为q次都是查询操作,并没有要求在线更新和查询,所以我们想到用离线算法,先把全部的输入接收,然后离线算出最后打出结果. 这题的思路是把所有的建筑物按照高度从大到小排序,然后所有的查询按照x从小到大排

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

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