BZOJ 4299 Codechef FRBSUM | 主席树
题目大意:
对于一个可重集,如果前 i 个数能表示到 max,新来一个数 x:如果 x <= max + 1,则能表示到 max + x;如果 x > max + 1,则只能表示到 max。
由此推出,若一个子集 S 能够表示到 max,则 max = sum{i} (i <= max + 1, i ∈ S)。
如果想不明白,我们详细解释一番:
一个子集能够表示到 max,则 max = 子集中小于等于 max + 1 的所有元素之和。根据上面粉色的定理,max 一定是由小于等于 max + 1 的元素加起来的;
而对于大于 max + 1 的元素,它并不能使 max 的值发生改变,所以不进行求和。
也就是不断扩展max的值,直到小于等于max + 1的元素无法凑出max + 1,max即为答案。
举个栗子:
集合 {1, 2, 4, 9}。max 初始值为 0。
1. 集合中小于等于 max + 1 的数:1 >= max + 1。max = 1。
2. 集合中小于等于 max + 1 的数:1 + 2 >= max + 1。max = 3。
3. 集合中小于等于 max + 1 的数:1 + 2 + 4 >= max + 1。max = 7。
4. 集合中小于等于 max + 1 的数:1 + 2 + 4 < max + 1。max + 1 即为最小的不能表示的数。
用tree(i)表示前 i 个数的状态,结点储存某个数出现的次数。问题就转化成了在一段区间内,权值小于等于某个数的和。