zoukankan      html  css  js  c++  java
  • HDU

    题意:有一排建筑,每座建筑有一定的高度,宽度可以忽略,求在某点的平地上能看到天空的最大角度。

    网上的做法基本都是离线的...其实这道题是可以在线做的。

    对于向右能看到的最大角度,从右往左倍增维护每个时刻的单调栈(凸壳),对于每个询问,先二分找到它右面的第一个建筑的位置,然后在对应的凸壳上倍增找到切点即可。

    向左看把x坐标对称一下就行。

    复杂度$O(nlogn)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 typedef double db;
     5 const db pi=acos(-1);
     6 const int N=1e5+10,inf=0x3f3f3f3f;
     7 int n,m,ka;
     8 struct P {
     9     db x,y;
    10     P operator-(const P& b) {return {x-b.x,y-b.y};}
    11     db rad() {return atan2(y,x);}
    12     bool operator<(const P& b)const {return x<b.x;}
    13 } a[N];
    14 struct D {
    15     P p,v;
    16     bool operator<(const D& b)const {return p<b.p;}
    17 };
    18 db cross(const P& a,const P& b) {return a.x*b.y-a.y*b.x;}
    19 struct Solver {
    20     int F[N][20];
    21     D b[N];
    22     void build(P* a) {
    23         b[n]= {a[n],{0,-1}};
    24         for(int i=1; i<n; ++i)b[i]= {a[i],a[i+1]-a[i]};
    25         for(int k=19; k>=0; --k)F[n][k]=n;
    26         for(int i=n-1; i>=1; --i) {
    27             int j=i+1;
    28             if(cross(b[j].p-a[i],b[j].v)>0) {
    29                 for(int k=19; k>=0; --k)
    30                     if(cross(b[F[j][k]].p-a[i],b[F[j][k]].v)>0)j=F[j][k];
    31                 j=F[j][0];
    32             }
    33             F[i][0]=j;
    34             b[i].v=a[j]-a[i];
    35             for(int k=1; k<20; ++k)F[i][k]=F[F[i][k-1]][k-1];
    36         }
    37     }
    38     db qry(P px) {
    39         int i=lower_bound(b+1,b+1+n,(D) {px, {0,0}})-b;
    40         if(cross(b[i].p-px,b[i].v)>0) {
    41             for(int k=19; k>=0; --k)
    42                 if(cross(b[F[i][k]].p-px,b[F[i][k]].v)>0)i=F[i][k];
    43             i=F[i][0];
    44         }
    45         return (b[i].p-px).rad()*180/pi;
    46     }
    47 } solver[2];
    48 int main() {
    49     int T;
    50     for(scanf("%d",&T); T--;) {
    51         printf("Case #%d:
    ",++ka);
    52         scanf("%d",&n);
    53         for(int i=1; i<=n; ++i)scanf("%lf%lf",&a[i].x,&a[i].y);
    54         a[++n]= {~inf,0},a[++n]= {inf,0};
    55         sort(a+1,a+1+n);
    56         solver[0].build(a);
    57         for(int i=1; i<=n; ++i)a[i]= {-a[i].x,a[i].y};
    58         reverse(a+1,a+1+n);
    59         solver[1].build(a);
    60         for(scanf("%d",&m); m--;) {
    61             db x;
    62             scanf("%lf",&x);
    63             printf("%.10f
    ",180-(solver[0].qry({x,0})+solver[1].qry({-x,0})));
    64         }
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    求求你,快去学习吧!!
    研究生英语读写译----topic3
    SQL----where 和 on 的区别
    SQL----语句执行顺序
    SQL----Inner Join、 Outer Join、Cross Join理解
    将一般的数值转换为金额格式(分隔千分位和自动增加小数点)
    伪元素 before 和 after 各种妙用
    抽空笑一笑
    别笑抽咯
    JavaScript继承方式详解
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11760789.html
Copyright © 2011-2022 走看看