从题目给的图片可以得到一个提示,我们将某一个斜坡(不妨假设斜率为正)变成一条直线,那么如果我们瞭望塔建在了这条斜坡的右边,则瞭望塔的顶端一定要在这条直线的上方,否则的话就看不到这个斜坡。进一步地,假设我们已经确定了瞭望塔的位置,那么:在其左边的斜率为负的斜坡都能被看到,斜率为正的斜坡能被看见当且仅当其延长的直线在瞭望塔顶端的下边;在其右边的斜率为正的斜坡都能被看到,斜率为负的斜坡能被看见当且仅当其延长的直线在瞭望塔顶端的下边
于是不难发现这是一个半平面交的问题,我们求出所有斜坡延长的直线的半平面交,那么答案候选点肯定子啊半平面交的边界上。进一步地可以知道,答案候选点一定在半平面交的拐点或者是过某个村庄山峰顶点作垂直于\(x\)轴的直线与半平面交边界的交点(因为如果都不是,那么我们将点向左边移动或者向右边移动,答案不会变得更差甚至可能会更好)
于是就变成模板题了
但是说一下我们的板子的问题:为什么最后需要让队首再去更新一遍队列?实际上这一个问题在OI-wiki中有阐述,可以看一下。但是这道题目的半平面交的所有边界的斜率,是从\(-\frac{π}{2}\)逐渐递增到\(\frac{π}{2}\)的,肯定不会出现OI-wiki所说的问题,于是就不用让队首再去更新一遍队列。如果更新了会发生什么问题?你会发现样例二(Acwing有两个样例)过不了,原因就在于on_right
函数,我们是小于等于判断的,这样会导致样例二全部都弹出去,我们要么将小于等于改成小于,要么不让队首再去更新一遍队列。这个改动是由于图形的特殊性质导致的。但是有些时候角度就是会设计\([-π,π]\)的所有角度怎么办?以OI-wiki的讨论为例,他画的那个图,我们加入一个外边界就好了,如下图: