la4108

来源:互联网 发布:c语言自学 编辑:程序博客网 时间:2024/06/07 23:52

此题是线段树的基础题。

本来我还以为这题要用到扫描线。后面把题目仔细看了一下其实根本没有那么复杂就一个区间更新的。

而且此题不用离线。因为我每次输入的高度都在前一个的基础上判断,所以在线算就好了

然后此题也不用build,不用query 只用一个update就好了。

update每次反回最可行的区间长度,然后用sum统计每次的区间长度就好了。

此题一开始想简单了。以为只需要一个maxv就能维护整棵树,当你当前的的查询高度h大于maxv的时候就反回当前区间长度。

后来自己用sample模拟了下发现当你你一组数据(5 11 3 )输进去后反回6的值,当第二组数据(1 10 1)的时候就可能有两种如果我不pushdown反回的是9(为什么是9下面说)的长度,那么就是全部的长度,那么我就相当于没有比较3的高度,但是我想我这个思路应该是没错的。

后来我就画1-15的线段当你第一组数据的时候会赋值5-8线段中的6,7,8那么我如果不把值传上去5--8这个父亲就是0,传上去就是3.那么如果我1,10的区间是2,10。那么5-8这个区间肯定在里面。当访问5-8这个区间的时候如果是3就退出去(这样就没有访问5)如果是0那么反回5-8的全部长度所以这里就没有比较3了。【但是还有方法就是全部扫描到叶子节点。那么这样就知道了单点的maxv了,但是这样复杂度就会很高,就相当于每个点的访问,显然是不对的。】那么既然这样我就加个vis来判断好了。即我是否访问过当前点。是的就赋值为1不是就赋值为0.那么此时情况还是没有改变5-8的情况,因为5-8是访问了但是maxv的值是3,且vis等于0(因为pushdown下去了)那么此时当max>h时候我就继续往下访问。然后5访问到了。现在到7-8由于7-8的h是3我应该在此处就反回,那么此时我vis是访问过的,且max的值是3,所以我就可以反回了。这样我就可以了扫到点了。

还有一个优化就是保存最小值,当最小值大于h的时候就直接跳回了。

如果当前点是访问过的点,那么就把max值赋值到min中以保存前一个max

当在区间范围内的时候:当最小值大于h的时候直接反回0,当最大值小于当前访问高度的时候就更新最大值并返回长度。

这里要介绍1-10的区间是2-10由于此题的长度是个连续的量,所以点都不是连续的,那么实际的长度呢就是(l-1,r】的左开右闭区间,那么长度就是r-l+1,那么要离散成实点,就要在l+1