Problem Statement
给定n个瓶子,编号从0~n-1,一开始所有瓶子都是空的 每个瓶子最多插入一朵花,实现以下两种类型的操作 操作 1 from flower : 一共有flower朵花,从from位置开始依次插入花朵,已经有花的瓶子跳过 如果一直到最后的瓶子,花也没有用完,就丢弃剩下的花朵 返回这次操作插入的首个空瓶的位置 和 最后空瓶的位置 如果从from开始所有瓶子都有花,打印"Can not put any one." 操作 2 left right : 从left位置开始到right位置的瓶子,变回空瓶,返回清理花朵的数量will be discarded.
Solving
将有花的花瓶位置上的值设置为1,没有花的花瓶则为0,一段区间中所有花瓶中花的数量即为这段区间的区间和,对于这个问题我们可以用线段树来维护,上述即为操作二的实现原理,现在我们来详细分析以下操作一如何用线段树进行维护:
显然的,如果给定的位置后面所有的花瓶里都有花,即没有任何空位放置新的花朵,此时直接输出Can not put any one,在程序中体现为Length = (n - 1) - l + 1 == st.querySum(1,l,n-1)
随后我们定义 leftzero 为后面所有花瓶中空花瓶的总数,其中cnt为输入值,表示从from位置往后插cnt朵花,此后有两种情况:
- cnt <= leftzero 意为剩余的花瓶足够插下cnt总数的花朵,所以此时的左右边界为 第一次插花的位置 与 第cnt次插花的位置
- cnt > leftzero 意为剩余的花瓶不足以插上总数为cnt的花朵,此时的左右边界为 第一次插花的位置 与 第leftzero次插花的位置
现在我们的问题就到了如何获取第X次插花位置上,对于[from,n -1]找到第X次插花位置,可以使用二分进行求解:
|
|
对此得到所有需要的数据,我们只需要在线段树中维护一个区间覆盖的功能,插上和清理的花的区间按区间模拟即可:
|
|