Statement
给长度为 \(n\) 的单调不上升序列 \(A\),\(B\) 为 \(A\) 的后缀和。你最开始在 \((n,1)\),要花费最小的代价跳到 \((1,1)\)。当你在 \((x,y)\) 时有两种选项:不花费任何代价跳到 \((x-1,y+1)\),或是花费 \(B_x\) 的代价跳到 \((x,\lceil\frac{y}{2}\rceil)\)。
\(n,A_i\le 10^6\)。
Solution
神仙题,不看标题猜不出一点,猜出来证不了一点
维护一个堆,开始让 \(A\) 中所有元素入堆,每次选堆中最小的两个数 \(a,b\),把 \(a+b\) 累加进答案,并把 \(a+b\) 加入堆。其实就是做一个最小哈夫曼树,也是最简单的“合并果子”。
证明:
首先
在哈夫曼树中,每个叶节点会在它的所有祖先中贡献一次权值,那么在最小哈夫曼树中,深度较深的叶节点一定设置着权值较小的 \(A_i\)。给定的 \(A_i\) 已经预先排成降序,即 \(A_i\) 是第 \(i\) 大的叶节点。
考虑一个问题:所有 \(A\) 组成的哈夫曼树中代价最小是多少。代价定义为这棵树所有节点权值之和。
假装我们不会贪心,考虑 DP。
为了确定出一棵哈夫曼树的代价,我们只需确定每个叶子的深度,又因为 \(A_i\) 降序排列,故 \(A_i\) 的深度单调递增,根据整数划分数 trick 我们可以通过两种操作唯一地确定出深度序列,与每种代价一一对应:
- 把 \(A_i\) 放置在第一个空叶节点处。
- 把所有空叶节点的深度 \(+1\),这时空叶节点数翻倍。
于是就可以做了!设 \(g(i,j)\) 表示,现在正在决策 \(A_i\) 的位置,现在共有 \(j\) 个空叶节点的最小代价。有两种可能:
- 我们可以给 \(A_i\) 分配一个空叶节点,\(g(i,j)\to g(i+1,j-1)\)
- 还可以给所有 \(j\) 个空叶节点分配两个儿子,空叶节点数翻倍,\(g(i,j)\to g(i,2j)\)
其中第二种操作会增加 \(\sum_{p\in[i..n]}A_p=B_i\) 的代价。初值为 \(g(1,1)=0\),答案为 \(g(n,1)\)。
发现这个转移和上面 \(f\) 的转移一模一样!!!然后我们马上又会贪心了,于是做完了。
不过 \(j\) 不是偶数时 \(f(i,\lceil\frac{j}{2}\rceil)+B_i\) 会不会影响答案呢?
不会,因为此时总会多加一个 \(A_i\),一定不会比从 \(f(i-1,j+1)\) 来优。
怎么想到的啊 QAQQAQQAQQAQQAQ