叹息之墙详细版

 

关于点与线段的关系,说明如下:

 

首先明确一条线段有N个点,里面只有N-1边

设第1条边,其长度为点2坐标-点1坐标

设第2条边,其长度为点3坐标-点2坐标

于是我们给某个点i打上标志,则代表由点i与点i+1构成的线段被选中

 

然后我们假设每个点都是可以突破的,但注意试题要我们求的是不可突破的点。

那如何来求呢?

基于下面这个最简单的想法:

如果一段区间[L,R], 如果我们将中间所有的点都突破了的话

则最终获得冲击力为这段区间的长度。

但如果这个冲击力小于左右边界的墙的高度话,那中间的点也白突破了

这一段的长度就要计算在结果当中

例如下图中

 

 

 

区间[2,5]这一段是可以突破的,因为长度为3,但两边的高度仅为1和2

但整个区间[1,9]长度为8,但两边的高度为17,18,明显突破不了。于是

整个区间要计算在结果当中。

 

这样做的好处在于:

如果我们按高度值进行排序,不断看高的墙所形成的区间,哪些是不能突破的。

则这些区间内部的点是无需再计算的。

于是我们将输入数据将高度进行降序排列

由于高度值是有可能相等的,并且排序后,点的顺序就打乱了。

但每个点的坐标值是互不相同的,并且坐标值巨大啊!

于是我们要建立一个映射,从坐标到点的顺序

例如,在上图中坐标值为1的点,是坐标轴上从左到右第1个点

坐标值为2的点,是坐标轴上从左到右第2个点

坐标值为5的点,是坐标轴上从左到右第3个点

坐标值为9的点,是坐标轴上从左到右第4个点

接下来,我们按权值从大到小进行枚举

 

当枚举到一个点,我们是知道它的高度与坐标值,但注意此时是不能直接得到

这些点在坐标轴的顺序的,必须通过刚才建立的map映射才知道。

将这些点的坐标放入一个set 中

先放入高度为18,加入set后,只有它一个点,即它的左右都没有点,所以什么也不做

再放下高度为17的点,加入set,此时发现在它的右边有点。

想一下,如何确保知道一个点的左边有点,或者右点有点

这个高度为17的点,它左边就没有点哟

对于一个集合的访问,一定要注意不要访问到无效的地址上。

于是取同这两个点的坐标值,差值为9-1=8

并且这个8是小于我们刚才加入的点的高度值17的。

这就说明这两者之间的所有点都是不能被突破的

此时根据坐标值到点的顺序这个映射,得到

高度为17的点,是坐标轴上第1个点

高度为18的点,是坐标轴上第4个点

于是这两个点之间的所有点即1,2,3这3个点,及它们代表的线段均是不可突破的。

 

接下来加入高度为2的点,发现这个点已打了不可突破的标志,所以不用管了

接下来加入高度为1的点,发现这个点已打了不可突破的标志,所以不用管了

 

最终统计结果

发现1这个点打了标志,于是点1到点2的距离要加入

发现2这个点打了标志,于是点2到点3的距离要加入

发现3这个点打了标志,于是点3到点4的距离要加入

 

接下来请同学们画一下这个样例的过程

 

 

 

其实这个做法还是有点难想的,而下面这个做法就清爽多了

按坐标从小到大排序

然后对于第i条线段[L,R],看能不能突破,所谓突破满足两个条件

1:这一段左边的高度<L与R的距离差

2:L点的左边那个点,被打上过突破的标志,这样才说明它逃出来了。

于是f[0]及f[N]要事先打上被突破的标志。这样在求第一段的时候,如果满足条件1,再加上f[0]已是突破状态,于是f[1]也就突破了。

当然也有可能没满足条件1,但在求第二段的时候,因为距离的累加,于是满足条件1了,于是第一段也就突破了。

 

posted @ 2022-12-12 22:05  我微笑不代表我快乐  阅读(331)  评论(0编辑  收藏  举报