// 鼠标点击特效 //

BalticOI 选做

BalticOI 选做

[BalticOI 2024]Wall

这种做法题解区好像没有,所以讲一下,比较有意思。

答案可以用 \(\sum H - \sum h\) 来算。

先考虑 \(\sum h\) 的部分,权值一定是 \(\sum (a_i+b_i)2^{n-1}\)

重点在于 \(\sum H\) 的部分。我们考虑使用这么一种计算方法:\(\sum [H \geq d]\) 。考虑固定一个 \(d\) 如何计算答案,那么现在我们就只关心 \(a_i,b_i\) 是否大于等于 \(d\) 了,记录 \(num_i\) 表示 \([a_i \geq d]+[b_i \geq d]\) 。在一个序列中,\(H\) 大于等于 \(d\) 的元素一定是一个连续的区间,我们枚举这个区间 \([l,r]\) ,然后去计算 \([l,r]\) 作为区间内元素都大于等于 \(d\)极大区间 的序列数量。

\(l=r\)

对于 \(l\) 位置本身而言,因为要求区间元素大于等于 \(d\) ,故有 \(num_i\) 种选择。对于 \(i \neq l\) 而言,要求元素严格小于 \(d\) ,所以有 \(\prod_{i \neq l} (2-num_i)\) 种选择。

故这种情况的贡献就是 \(num_l \times \prod_{i \neq l} (2-num_i)\)

\(l \neq r\)

类似于 \(l=r\) 的,两个端点处都要求权值大于等于 \(d\) ,所以有 \(num_{l}\times num_r\) 种可能性。既然左右端点确定了,那么 \((l,r)\) 内的元素可以自由选择,故有 \(2^{r-l-1}\) 种可能性。在区间外的元素贡献同 \(l=r\)

这种情况的贡献是 \((r-l+1) \times num_l \times num_r \times 2^{r-l-1} \times \prod_{i \notin [l,r]} (2-num_i)\)

我们发现 \(l=r\) 不过是 \(l \neq r\) 的特殊情况。。。

对于这种二元组统计问题,可以想到使用分治结构去计算。我们考虑线段树。

看看答案怎么合并,一个节点的合法二元组由两个儿子内的答案和跨越分治中心的区间 \([l,r]\) 构成。一定需要记录一下三种信息:

  1. \(ans_i\) 表示区间内所有合法二元组的贡献和。
  2. \(prew_i\) 表示区间内所有合法的前缀 \(l\) 的贡献和。
  3. \(sufw_i\) 表示区间内所有合法的后缀 \(r\) 的贡献和。

先考虑 \(ans_i\) 的合并。

最为简单的就是 \(ans_i=ans_{ls}+ans_{rs}\) 。然后考虑利用 \(sufw_{ls}\)\(prew_{rs}\) 合并出答案。这里有一个棘手的点:

  • \(prew_i\) 记录的信息类似于 \((-l+1)\times num_l \times 2^{x} \times \prod_{j<l}(2-num_j)\)
  • \(sufw_i\) 记录的信息类似于 \(r\times num_r \times 2^x \times \prod_{j>r}(2-num_j)\)

事实上,我们需要计算的答案形式与 \(prew_i\)\(sufw_i\) 都不同。系数不同,贡献 \((r-l+1)\) 也与 \(-l+1,r\) 不同。但是我们可以拆贡献:

\((r-l+1) \times num_l \times num_r \times 2^{r-l-1} \times \prod_{i \notin [l,r]} (2-num_i)\) 可以被表示为:

\(r \times num_l \times num_r \times 2^{r-l-1} \times \prod_{i \notin [l,r]} (2-num_i)\)

\((-l+1) \times num_l \times num_r \times 2^{r-l-1} \times \prod_{i \notin [l,r]} (2-num_i)\)

我们只需要额外维护 \(pre_i,suf_i\) 的不带贡献形式 \(pre_i,suf_i\) 形式就可以了。

  • \(pre_i\) 记录的信息类似于 \(num_l \times 2^{x} \times \prod_{j<l}(2-num_j)\)
  • \(suf_i\) 记录的信息类似于 \(num_r \times 2^x \times \prod_{j>r}(2-num_j)\)

那么就有 \(ans_i=(sufw_{ls}\times pre_{rs}+suf_{ls}\times prew_{rs})\)

接下来考虑 \(pre_i\)\(prew_i\) 的转移,\(suf_i\)\(sufw_i\) 的转移十分类似,这里就不讲了。

\(pre_i\) 也是由两个部分组成:\(pre_{ls}\)\(x \times pre_{rs}\) 。就是前缀在左儿子还是右儿子中的两种情况。记录 \(seg_i\) 表示 \(i\) 节点所管辖的线段长度,则左儿子的转移是十分简单的:\(pre_i=pre_{ls}\times 2^{seg_{rs}}\)\(prew_i\) 的转移是一模一样的。

考虑 \(l\) 在右儿子内,转移的时候左儿子的元素均会贡献 \(\prod (2-num_j)\) 的系数,所以额外记录 \(t_i\) 表示区间内元素 \((2-num_j)\) 的积。则:\(pre_i=t_{ls}\times pre_{rs}\)

\(t\) 本身就是 \(t_i=t_{ls}\times t_{rs}\)

最后答案就是 \(ans_{root}\)

这么计算的好处在于分治结构可以动态。那么我们让 \(d\) 从小到大,对于每一个元素而言,\(num_i\) 会经历 \(2\)\(1\)\(1\)\(0\) 的过程,在线段树上单点修改一下即可。

时间复杂度 \(O(n \log n)\)

[BalticOI 2021] The short shank

提供一个比较好想的做法.

考虑如果一个隔板都不放,那么每一个犯人有两种造反的可能性:

  • 自己造反的时间的时间 \(t_i \leq T\) .(一类犯人)
  • 自己造反的时间虽然大于 \(T\) ,但是存在一个位于其之前的犯人满足 \(t_i \leq T\) ,并且可以通过传导的方式使得这位犯人在 \(T\) 之前造反.(二类犯人)

对于一类犯人,没救了.但是可以通过插入隔板的方式阻断第一类犯人造反后的传导,以减少第二类犯人的造反.接下来需要集中注意力:

性质1:假设对于一个二类犯人 \(i\) ,可以通过传导的方式使得其造反的,编号最大的犯人为 \(f_i\) .则当 \(f_i\)\(i\) 之间存在隔板的时候,犯人 \(i\) 不会造反.

这个就不需要证明了,应该是比较显然的.所以我们就提取出了若干个区间 \([l_i,r_i]\) .然后需要选择一些点,使得包含这些点的区间尽可能多. 体现在题目中的含义就是:点代表着隔板,一个区间内存在隔板就会减少一个二类犯人的造反.

但是这样也不是很好做,我们猜想区间是否存在一些性质:

性质2:对于两个二类犯人 \(i,j\) ,\([f_i,i],[f_j,j]\) 要么包含,要么不相交.

证明:就是证明不会出现 \(f_i<f_j<i<j\) 的情况出现.注意到 \(f_j\) 可以使得 \(j\) 造反,而不可使得 \(i\) 造反.而传导到 \(j\) 的时间消耗比 \(i\) 大,所以此时 \(f_i\) 应当是 \(f_j\) 才对.与假设不成立.所以不会出现仅相交的情况.

我们获得了这个重要性质,像一下,区间要么不相交,要么包含.容易想到树形结构.我们考虑对于一个区间,让最小的,包含其的区间向他连边,就得到了一个森林.

问题进一步被转化为选出若干个节点,使得他们到根的路径并尽可能的大.这个问题十分经典,长链剖分选前 \(d\) 长的长链即可.

时间复杂度为 \(O(n \log n)\) .因为找到 \(f_i\) 需要时间,方法有很多.可以使用单调栈二分的方式实现.

posted @ 2024-11-01 00:48  dan-da-dan  阅读(93)  评论(0)    收藏  举报