HDU 5033 Building

维护一个单调队列(用stack实现)

以左边为例,如果 2 位置 高度为 10 ,3 位置 高度为 2 , 4 位置 高度为 5

则队列中存有 2、4 位置

然后每次计算人的时候计算整个队列里的情况

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include <algorithm>
#define maxn 100005
#define maxq 100005
#define PI acos(-1.0 )
#define eps (1e-10)

using namespace std;

struct Building
{
        double x;
        double h;
        double lAng;
        double rAng;
}building[maxn];

struct Query
{
        int id;
        double pos;
        double lAng,rAng;
}query[maxq];
int t,cas,n,q;

bool cmp1(Building a,Building b)
{
        return a.x+eps<b.x;
}

bool cmp2(Query a,Query b)
{
        return a.pos+eps<b.pos;
}

bool cmp3(Query a,Query b)
{
    return a.id<b.id;
}
stack <int> pre;

int main()
{
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                    scanf("%lf",&building[i].x);
                    scanf("%lf",&building[i].h);
            }

            scanf("%d",&q);

            for(int i=1;i<=q;i++)
            {
                    scanf("%lf",&query[i].pos);
                    query[i].id=i;
            }

            sort(building+1,building+1+n,cmp1);
            sort(query+1,query+1+q,cmp2);
            while(!pre.empty()) pre.pop();

           building[1].lAng=0.0;
          pre.push(1);
           int qIndex=1;

while( qIndex<=q && query[qIndex].pos>building[1].x&& query[qIndex].pos<building[2].x )
                {
                    double calAng;
                    while(!pre.empty() && (calAng=(building[pre.top()].h)/fabs(query[qIndex].pos-building[pre.top()].x))<building[pre.top()].lAng )
                        pre.pop();
                    query[qIndex].lAng=calAng;
                    qIndex++;
                }

           for(int i=2;i<=n;i++)
           {
                    double tmpAng;
                    while(!pre.empty() && (tmpAng=((building[pre.top()].h-building[i].h) /fabs(building[i].x-building[pre.top()].x)) )<building[pre.top()].lAng)
                              pre.pop();

                     building[i].lAng=tmpAng;
                     pre.push(i);

                while( qIndex<=q && query[qIndex].pos>building[i].x&& query[qIndex].pos<building[i+1].x )
                {
                    double calAng;
                    while(!pre.empty() && (calAng=(building[pre.top()].h)/fabs(query[qIndex].pos-building[pre.top()].x))<building[pre.top()].lAng )
                        pre.pop();
                    query[qIndex].lAng=calAng;
                    qIndex++;
                }
           }

            while(!pre.empty()) pre.pop();
           building[n].rAng=0.0;
            pre.push(n);
           qIndex=q;

while( qIndex>=1 && query[qIndex].pos<building[n].x && query[qIndex].pos>building[n-1].x )
                {
                     double calAng;
                    while(!pre.empty() && (calAng=(building[pre.top()].h)/fabs(building[pre.top()].x-query[qIndex].pos)) <building[pre.top()].rAng)
                        pre.pop();
                    query[qIndex].rAng=calAng;
                    qIndex--;
                }

           for(int i=n-1;i>=1;i--)
           {
               double tmpAng;
                    while(!pre.empty() && (tmpAng=( (building[pre.top()].h-building[i].h)/fabs(building[pre.top()].x-building[i].x)))<building[pre.top()].rAng)
                              pre.pop();

                     building[i].rAng=tmpAng;
                     pre.push(i);

                while( qIndex>=1 && query[qIndex].pos<building[i].x && query[qIndex].pos>building[i-1].x )
                {
                     double calAng;
                    while(!pre.empty() && (calAng=(building[pre.top()].h)/fabs(building[pre.top()].x-query[qIndex].pos)) <building[pre.top()].rAng)
                        pre.pop();
                    query[qIndex].rAng=calAng;
                    qIndex--;
                }
           }
//for(int i=1;i<=n;i++)
 //   printf("%.10lf ",building[i].rAng/PI*180.0);
//printf("\n");
           sort(query+1,query+1+q,cmp3);
           printf("Case #%d:\n",cas);//cout<<q<<' ';
           for(int i=1;i<=q;i++)
           {
              //printf("%.10lf %.10lf\n",query[i].lAng/PI*180.0,query[i].rAng/PI*180.0);
               printf("%.10lf\n",180.0-(atan(query[i].lAng)+atan(query[i].rAng))/PI*180.0 );
           }
    }
    return 0;
}
/*
10
2
1 0
3 0
1
2
Case #1:
180.0000000000
3
1 0 3 0
4 0.00000001
1
2
Case #2:
179.9999997135
3
5 1
1 4
2 3
1
4
Case #3:
78.6900675260
3
3
2 1
5 1
1 2
1
4
Case #4:
78.6900675260
180.0000000000
3
3
2 1
5 1
1 2
1
4
Case #5:
78.6900675260
180.0000000000

*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值