1. CF1615E Purple Crayon

difficulty - 2400

code

对着数据调试,也不知道算不算贺了,先放在没贺的这边好了。

\[val=w(r-b)=(n-r-b)(r-b)=b^2-nb+(n-r)r \]

这说明了:当 \(r\) 确定后,\(b\) 越接近 \(n/2\) 越好。

我们知道,当一个结点变成红色之后,其所有包括自己的祖先结点都不可被染蓝;假设所有依然可以被染蓝的结点数量为 \(s\),则 \(b\) 可取遍 \([0,s]\)

证明:经典剥叶子套路。

因此,如果选手 \(A\) 想好了他要染 \(r\) 个结点为红色,则他剩余的工作就是让 \(s\) 最小,即让这 \(r\) 个结点到根的链的并集最大化。

这里我们可以有两种方式求出树链的并的最大值。

  • 直接用线段树维护当前状态下,每个点到根的路径上还有多少个点不在并集中,每次贪心地取出最大的点即可(可以发现一定为叶子)。取出点后修改时,暴力跳 \(fa\) 并在线段树上打 \(tag\) 做区间减法和全局最大值。

  • 长链剖分。贪心地取出剩余链中的最长链即可。这个必须记住。

于是我们每次得到一个 \(r\) 和一个 \(s\),用初中数学知识求出选手 \(B\) 能让 \(val\) 达到的最小值即可。

还有一个情况没有考虑进去。当选手 \(A\) 覆盖的点的个数 \(k>\) 叶子个数 \(m\) 时,选手 \(B\) 已经没有任何染蓝色的空间了。这时候选手 \(A\) 不必把整棵树都染成红色,他可以选择让 \([m,k]\) 个点变成红色,暴力枚举即可。

时间复杂度:\(\mathcal{O}(n+k)\)\(\mathcal{O}(n + k\log n)\)

2. CF1799F Halve or Subtract

difficulty - ?

code

好题但是简单题,放 \(1+2\)\(\text{F}\) 过分了。

考虑对于每个数有四种状态:除 \(+\) 减,除,减,什么都不干。

  • 引理 \(1\):操作全用完一定不劣。

  • 引理 \(2\):对于除 \(+\) 减的数,一定先除后减。

接下来将所有数从大到小排序,得到 \(a_1,a_2,\cdots a_n\)

显然除 \(+\) 减的一定是一段前缀 \(k\)。直接枚举前缀 \(k\)

为了方便,令 \(\max(0,k1+k2-n)\leq k\leq \min(k1,k2)\)。鉴于引理 \(1\),这样做没问题。

剩下了 \(k1-k\) 个除和 \(k2-k\) 个减。

  • 引理 \(3\):除了 \(a_1,a_2,\cdots a_k\) 之外,进行操作的数字必然是 \(a_{k+1},a_{k+2}\cdots a_{k1+k2-k}\)

对于 \(a_{k+1},a_{k+2},\cdots a_{k1+k2-k}\),按照与 \(b\) 的大小关系,分成两段:\(a_{k+1},a_{k+2},\cdots a_p\)\(a_{p+1},a_{p+2},\cdots a_{k1+k2-k}\)

假设已经给两段分配好了各自除和减的数量,怎么确定具体的对每个数字的操作呢?

    1. 对于不小于 \(b\)\(a_{k+1},a_{k+2},\cdots a_p\)

减操作的贡献一定是 \(-b\),而除操作对于 \(a_x\) 的贡献是 \(-\lfloor a_x\rfloor\)

既然减给谁都无所谓,那么显然是给大的数除,给小的数减。

即对于 \(a_{k+1},a_{k+2},\cdots a_p\) 的操作是: \(///---\)

    1. 对于小于 \(b\)\(a_{p+1},a_{p+2},\cdots a_{k1+k2-k}\)

对于 \(a_x\),减操作的贡献是 \(-a_x\),除操作的贡献是 \(-\lfloor a_x\rfloor\)。显然,我们应给大的数减,给小的数除。

即对于 \(a_{p+1},a_{p+2},\cdots a_{k1+k2-k}\) 的操作是:\(---///\)

发现了什么?从 \(a_{k+1}\)\(a_{k1+k2-k}\) 的操作是先除,再减,最后除。

所以我们不用真的对 \(a_x\) 根据 \(b\) 分段,只需要在枚举 \(k\) 之后,再枚举减的一段的开头 \(a_p\) 即可。可以通过简单 \(\mathcal{O}(n)\) 预处理达到单次 \(\mathcal{O}(1)\) 算出一个方案的答案。

时间复杂度 \(\mathcal{O}(n^2)\)