题意:排成一行的旅馆房间
checkin时找到最靠左的空闲的长度>=d的连续区间,输出区间的左端点\(r\)并入住
checkout时把从x开始的长度为d的区间变为空闲
线段树的区间合并问题?
空闲0\1表示,区间置0\1可以用打标记来实现。
如何找到满足条件的区间端点\(r\)呢?线段树每个结点维护的信息为从区间左端点开始的全0序列的长度ls,从区间右端点开始的全0序列的长度rs,区间中最长的全0序列长度ms。如果线段树某个结点ms>=d,那么最长的区间可以来入住,最长区间有三种情况:完全在左儿子的区间,横跨左右儿子的区间,完全在右儿子的区间。因为\(r\)要满足最靠左,所以依次尝试上面三种可能情况。
注意在查询的时候下传标记。由于query函数写法的原因,如果某个区间被置为全0\1,那么这个区间一定满足ms[k] == ls[k]
,因此一定满足ms[k] < d
、ls[k] >= d
其中之一而退出。如果继续向下执行,那么结点k一定是没有标记的,不需要向下传标记。这也是为什么第一次交的时候没有push_down
也过了。
有了宏定义后代码精简了好多…
刚开始接触这类区间问题,还比较生疏…
1 |
|