Loading

CF878E Numbers on the blackboard

题目大意

一个 \(n\) 个整数的序列被写在黑板上。很快 Sasha 就会来到黑板前,开始下面的操作:

  • \(x\)\(y\) 是两个相邻的数字(\(x\)\(y\) 之前),然后他可以删除 \(x, y\) 并插入 \(x + 2y\) 来代替 \(x, y\)

他将执行这些操作,直到剩下一个数字。Sasha 喜欢大数字,会得到尽可能大的数字。

Nikita 想在 Sasha 之前走到黑板前,擦掉一些数字。

他有 \(q\) 个操作,在操作 \(i\) 中,他擦除第 \(l_i\) 个数字左边的所有数字和第 \(r_i\) 个数字右边的所有数字。第 \(l_i\) 和第 \(r_i\) 之间的所有数字都保留在黑板上。对于每一个操作,他都想知道 Sasha 的最终数字会有多大。这个数字可以很大,所以输出它模 \(10^9 + 7\)

题目思路

考虑这么一个事情,每个数 \(a_i\) 对于最后的数的贡献为 \(a_i \times 2^{p_i}\),这肯定是显然的,让我们推导出在操作的过程中有这么一个结论:\(p_i \le p_{i - 1} + 1\),这里来推导一下:

  • 考虑如果我们想要对 \(p_i\) 造成影响,肯定就要与 \(1 \sim i - 1\) 的数分别合并才行,当我们想要减少 \(p_i\) 的时候,\(p_{i - 1}\) 也会减少,因为最开始 \(i - 1\) 就必须与 \(i\) 合并,\(i\) 才能产生更多的贡献,只有在第一次合并产生贡献的一次操作时,\(p_i\) 才会比 \(p_{i - 1}\)\(1\),只要进行完这次操作后 \(i - 1, i\) 就捆绑在一起了,而在这之前,由于 \(i\) 与后面的数合并都不会使 \(p_i\) 发生变化,所以在合并 \(i - 1, i\) 之前,\(p_i \le p_{i - 1}\),综上,\(p_i \le p_{i - 1} + 1\)

这是第一步,也是最为重要的一步。

考虑到显然我们想让正数\(p_i\) 越大越好,负数的 \(p_i\) 越小越好,但是又要满足限制,我们考虑以下贪心:

  • 如果 \(a_i > 0\),那么直接令 \(p_i = p_{i - 1} + 1\)
  • 如果 \(a_i \le 0\),那么直接令 \(p_i = 0\)

这个贪心看起来很对啊,我们考虑这个贪心较为正确的一部分

  • 对于 \(a_i > 0\),令 \(i\) 之前距离 \(i\) 最近的 \(p_i = 0\) 的位置为 \(r\),我们要分两种情况讨论:
  1. \(\sum\limits_{j = r}^{i - 1} a_i^{p_i} > 0\),显然是接着 \(i - 1\) 继续加是比较好的。
  2. \(\sum\limits_{j = r}^{i - 1} a_i^{p_i} \le 0\),显然重新开一段能够弥补的答案没有继续接着 \(i - 1\) 加能够弥补的多。
  • 对于 \(a_i < 0\),我们还是讨论分两种情况:
  1. \(a_{i + 1} \le 0\),显然可以继续递推。
  2. \(a_{i + 1} > 0\),我们此时需要证明:重开一段比不重开的减去的代价要少,也就是说证明 \(a_i + 2 \times a_{i + 1} \ge a_i \times (p_{i - 1} + 1) + 2 \times a_{i + 1} \times (p_{i - 1} + 1)\),考虑解出来的式子是 \(a_i \times p_{i - 1} + 2 \times a_{i + 1} \times p_{i - 1} \le 0\)也就是说最后这一步是不一定对的,这个时候,就需要对贪心算法加以改进了。

考虑加上一步:

  • 对于一个数 \(x\),如果 \(x > 0\),与之前的一个连续块合并,如果合并完之后的连通块大小大于 \(0\),继续与前面的连通块合并,以此类推,直到不能合并为止。

为什么这个贪心是正确的呢?考虑如果继续往前合并,那么上述中 \(a_{i + 1}\) 的价值将被充分的发挥利用,这个时候其实就没有负数带来的贡献了。

然后从前往后依次贪心,不难发现合并可以用并查集维护,将询问离线下来后发现其实只是最左边的连续块需要断一下,用后缀和类似哈希的方式进行处理,然后就做完了。

posted @ 2024-02-27 21:06  Alexande  阅读(24)  评论(0)    收藏  举报