Building HDU - 5033(详解+维护斜率的单调栈+角度计算)

题目大意:T个测试用例,N个建筑物,Q条查询,输出查询的每个位置 能看到天空左右视角之和是多少,每条询问的位置左右必定是有建筑物的。

大致思路:维护一个斜率和高度(也就是斜率)的单调栈,将所有的点一起计算,将查询点高度赋值为0即可。通过高度差与点差计算出斜率,从单边进行计算,计算出左侧的角度,将数组反转或者从右侧出发,计算右侧的角度,注意角度是与垂线之间的夹角,不是水平的。每加入一个点,维护栈内的高度和斜率,也就是这个人能看到栈内所有的建筑物,如果看不到 ,被挡道就删掉,删除凹点即可。维护一个斜率绝对值递增的单调栈

这种情况所有点都被 挡住了

Building HDU - 5033(详解+维护斜率的单调栈+角度计算)_第1张图片

这种情况都没有被挡住所以直接算栈顶元素即可

Building HDU - 5033(详解+维护斜率的单调栈+角度计算)_第2张图片

所有的详解以及细节都在代码的注释里,与君共勉。

#include
using namespace std;
const int maxn=100100;
int n;
#define PI acos(-1)
 //圆周率,以前并没用过
struct node{
  int id;
  double h;
  double xi;
};
//id表示查询的下标,其hi=0,xi=qi;
node a[2*maxn];
node s[2*maxn];
double ans[2*maxn];
int cmp(node a,node b)
{
    return a.xi=2&&judge(s[top-1],s[top],a[i]))
          {
            top--;
            }//同样去除凹点;
          ans[a[i].id]+=digistangle(a[i],s[top]);
       }
       else
       {
 //  1 2
   //2 1
  // 5 1
  // 1
   //4//测试了很多数据
           while(top&&a[i].h>=s[top].h)//如果栈非空的话
            top--;//维护一个斜率以及高度的单调栈,将没有用的凹点去掉即可
           while(top>=2&&judge(s[top-1],s[top],a[i]))
            top--;//去除凹点;
           s[++top]=a[i];
       }
   }
}
void revers(int n)
{   int mid;
    if(n%2==0)
    mid=n/2-1;
    else
        mid=n/2;
    for(int i=0;i<=mid;i++)
    {
        node p=a[i];
        a[i]=a[n-i-1];
        a[n-i-1]=p;
    }
}//手动实现的反转
//
int main()
{

    int T;
    scanf("%d",&T);
    int flag=0;
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i

 

参考博客:

https://blog.csdn.net/xtulollipop/article/details/52558686?utm_source=blogxgwz0

你可能感兴趣的:(单调栈)