CF2066E 解题报告

CF1004E 解题报告

题目

你有 \(n\) 个桶,每个桶里有 \(a_i\) kg 的水,其中一个桶的水里有 \(0.114514\) kg的毒药。现在你可以比较任意两个桶的质量,同时你也可以将一定安全的桶里的水倒入任意一个桶里。现在对桶的序列进行 \(m\) 次修改,每次都会增加/减少一个有 \(x\) kg水的桶,请问对于最初的序列和每一次修改后的序列,是否一定可以找出那个桶里的水有毒?

数据范围: \(n,m \le 2 \times 10^5\)\(a_i,x \le 10^6\)

English version

Official solution

分析

首先,有所有桶里的水的质量互不相同的情况一定无解。

因此我们可以先将所有质量相同的桶里的水汇总到一起,设总量为 \(L\),并且将剩余的桶按质量从小到大列为 \(\{b_n\}\)

分析样例,我们发现:假设我们已经判断出 \(b_1,b_2,...,b_{i-1},b_i\) 是安全的,如果 \(bi\) 可以被判断是安全的,当且仅当:

  • \(b_i \le L + \sum_{j=1}^{i-1} b_j\)

  • \(b_{i+1}-b_i \le L + \sum_{j=1}^{i-1} b_j\)

先考虑第一种情况,我们称不满足这个等式的点是特殊的。我们发现特殊的点的个数不超过 \(log(b_n)\),因为每次遇到这类点后,等式的右边都会扩大一倍。

因此我们考虑开一颗线段树来快速找这些点。具体地,每一个点维护当前区间内 \(b_i-d_{i-1}\) 的最大值(\(d\)\(b\) 数组的前缀和数组)。

然后在线段树上搜索,如果儿子维护的值大于 \(0\),那么就遍历它,直到叶子节点。找到一个点最坏是 \(O(logn)\) 的,因此每次找到这些点的时间复杂度是 \(O(lognloga_n)\) 的。

接下来,我们再开一颗线段树,树上节点维护区间内 \(b_{i+1}-b_i\) 的最小值。对每一个特殊点 \(p\),我们在这棵线段树上询问 \([p+1,n]\) 的最小值。如果最小值满足等式二,那么就继续枚举下一个特殊点;如果不满足,那么我们就不能判断。

时间复杂度 \(O(nlognloga_n)\)

空间复杂度 \(O(nlogn+a_nloga_n)\)

总结

倍增思想的运用是套路的(见神秘数)。

考场上没有想到线段树维护特殊点。

代码

待补

posted @ 2025-07-12 15:04  XiaoZi_qwq  阅读(3)  评论(0)    收藏  举报