alias method/别名算法

alias method/别名算法

前言

一个在oi/acm比较少见的算法吧。。算法

从问题开始QAQ

有\(N(N>1)\)个物品,有属性\(d_i\),如今要平均放进\(N-1\)个盒子里,每一个盒子最多存在两个物品,物品能够分割。数组

当N=2时。

显然两个全放进一个盒子里就好了。数据结构

当N>2时。

显然咱们能够先算出每一个盒子须要放多少,设其为\(K\),因而\(\sum{d_i}=(N-1)K\)。
一共\(N\)个物品要放进\(N-1\)个盒子中,设其中\(d_i\)的最大值为\(mx\),最小值为\(mn\)。
性质1:\(mn<K\)
性质2:\(mn+mx>K\)
这两个性质比较显然,均可以用反证法证实的。
因而咱们能够直接让\(mn\)和部分\(mx\)来凑成K,多余部分放回去,因而物品和盒子可数均减小1,递归便可。ide

怎么实现

咱们须要维护增长元素,删除元素,询问最大最小值的一个数据结构,显然能够用个multiset,因而就能轻松作到O(nlogn)。优化

进一步优化

若是要维护最大最小值的话,就很难不带log。(悲)。然而实际上咱们也并不是必须取最值。
咱们考虑把物品分红两类,一类是\(d_i<K\),其他是另外一类。
因而咱们能够每次在两个类中各取一个凑一个K,而后放回剩余。
然而这么作会有个问题,到后面可能存在全部\(d_i\)全都小于\(K\)的状况。
其实这个状况下能够证实任意两个物品都能知足加起来不小于K(就不证了吧QAQ),因而按顺序合并就好。
因而如今的作法就能够作到空间O(n),时间O(n)了。递归

应用

一个随机事件包含\(n\)种状况,每种状况发生的几率分别为:\(p_i\),问怎么用产生符合这个几率的采样方法。
这种问题的解决方法不少,好比按照几率构造数组而后在上面随机。。
然而许多方法时间空间复杂度不够优秀,或者在大量数据采样时不能较好的符合发生几率。
应用别名算法,至关因而把这些总和为1的物品分到n-1的盒子里,每次采样先随机到一个盒子,再按照盒子内的比例随机一次。
就能作到O(n)的空间和时间预处理,每次O(1)的采样,而且采样结果比较符合事件几率。事件

相关文章
相关标签/搜索