CF1416E 题解

· · 题解

闲话:这是一个和其它题解不太一样的 dp 做法,比较容易想到但细节较多。

题意

给定一个 n 个正整数的序列 a_i,构造一个长度为 2n 的正整数序列 b_i,使得 b_{2i-1}+b_{2i}=a_i,且 b 连续相同的值形成的连续段个数尽可能少。求这个最小值。n\le 5\times 10^5

思路

比较容易的转化是最小化连续段数本质上就是最大化 b_i=b_{i+1}i 的个数,所以下面考虑求这个的最大值。先将所有 a_i 减去 2,这样 b 就是非负整数序列。考虑 b_i=b_{i+1} 有哪些可能性,发现如果是 b_{2i-1}=b_{2i},那么一定有 b_{2i}=\frac{a_i}2。这意味着对于这一类值而言,b 的值是可以确定的。这是一件很好的事情,因为确定了 b 的值就能够进行后续的很多操作。

我们来进一步分析一下所有这些相等位置的形态。首先我们确定一些 i 满足 b_{2i-1}=b_{2i},下面我们假定 l,r 满足 b_{2l-1}=b_{2l},b_{2r-1}=b_{2r},而对于 i\in (l,r),我们不关心其是否满足 b_{2i-1}=b_{2i},即使满足我们也不计入贡献,这样一定不会比最优解更优但最优解一定能取到。那么在这个区间内,我们只关心 b_{2i}=b_{2i+1} 的对数。我们又可以钦定一些 i,强制要求 b_{2i}\ne b_{2i+1},即使等于也不计入贡献,那么我们就可以将 [l,r] 也分成若干段 [l_i,r_i],其中每一段要求存在一种填数的方案,使得对于任意 l_i\le j<r_i,都有 b_{2j}=b_{2j+1}。特别地,对于第一段,需要保证 b_{2l}=\frac{a_l}2,最后一段同理。对于这个做法,如果我们能够快速判断一个区间是否合法,就可以快速计算贡献。

这样我们就有一个暴力的 dp,记 f_i 表示考虑了 b 中的前 2i 个位置,我们要求最后两个数等于 \frac{a_i}2,并且还要求 b_{2i+1}=b_{2i} 的答案(不考虑 2i2i+1 带来的贡献),记 g_i 表示考虑了 b 中的前 2i 个位置,最后一段不限制,但强制钦定 2i2i+1 不带来贡献的答案。记 T(l,r,vl,vr) 表示是否存在一种方案,使得 b_{2l-1}=vl,b_{2r}=vr,且任意 l\le i<r 都有 b_{2i}=b_{2i+1} 的合法的 b,若 vl,vr 中某一个为 -1 则表示没有限制。考虑如何转移:

这是从定义本身出发得到的转移,当然前两种也可以把 j 换成 j+1,这样不影响结果,形式可能更整齐一点。这个做法是 O(n^3) 的,因为 T 可以 O(n) 计算,所以下面我们先尝试优化 T 的计算。

先假定要算 T(l,r,-1,-1)。我们发现合法的 b_{2l-1} 一定是一段区间,所以考虑求出这段区间,那么自然 T(l,r,*,-1)T(l,r,-1,*) 也都可以求得了。假设 b_{2l-1}=x,发现确定了 x 之后每个 b_i 的值都可以唯一确定了。我们来关注所有 b_{2i} 的值。写一下可以发现规律,b_{2l}=a_l-xb_{2(l+1)}=a_{l+1}-a_l+xb_{2(l+2)}=a_{l+2}-a_{l+1}+a_l-x 等等。就是将 [l,i] 中所有 a 的值符号交替地求和得到的结果。预处理 (-1)^ia_i 的前缀和,即可 O(1) 查询一个位置的 b_{2l} 的值。注意到合法的条件就是所有 b_i 非负,那么就有若干不等式 b_{2l}\ge 0,每个不等式移项之后同样可以用这个前缀和表示,由于前缀和一端固定,所以分奇偶处理之后用 ST 表维护区间最小值/最大值,即可 O(1) 得到所有不等式解集的交,也就是我们要求的 b_{2l} 的取值区间。而 T(j,i,*,*)* 都不是 -1 的时候,还需要再加一步判断这两个值能否搭在一起,即根据 b_{2l} 的值算出的 b_{2r} 是否吻合。这样我们就可以 O(1)T,从而得到了一个 O(n^2) 的做法。

考虑进一步优化,我们发现对于后三种转移,若确定了 ijv 有被钦定值的一个(若都是 -1 则随便一个),随着另一个的远离,只会在区间上交上更多的区间,所以 T 的值是单调的。所以可以二分出可以转移到的区间,或可以向它转移的区间,使用线段树优化 dp 转移,这个可以做到 O(n\log n)。但第一种转移比较困难,原因是转移点并不单调,也不是一段区间,所以看起来比较难办。

不过我们可以根据这个 dp 的含义发现对于一个 i,只需要从最后一个能转移的 ji 转移即可。这是为什么呢?因为当 i 固定时,b_{2i} 被固定了,所以前面所有的 b 其实都已经被确定。这样如果有两个转移点 l<r,不管使用哪种转移,b_{2r-1} 总是等于 b_{2r}。而我们在 f_l\to f_i 的时候没有考虑这一个贡献,相反,若我们先从 f_l\to f_r,再从 f_r\to f_i,这一定合法,并且会计算这个贡献,因此一定更优。这样一来,我们只需要能够找到最后一个转移点即可。而从 j\to i 的转移,除了需要满足 j 在前面求出的 i 的可被转移到的区间中以外,还需要满足的条件是一个关于 a_i,a_j,s_i,s_js 是预处理的前缀和),以及 i,j 的奇偶性的线性方程。所以分 i,j 的奇偶性,将方程移项之后把关于 j 的项的值存入 map,查询关于 i 的项的值在对应 map 中的最大位置并判定是否合法即可。所以复杂度 O(n\log n),总复杂度 O(n\log n)

代码