AGC049E Increment Decrement
Solution
以前很少做 atcoder 的题,今天一做,果然难炸了。
哦,我做了不止一天啊,那没事了(主要自己又懒又菜
首先我们考虑单一序列咋做。先转化为初始序列为 \(\{0\}\),我们要转成 \(\{A_i\}\)。
对于单一序列,假如我们知道了所有操作二完成之后的序列,贡献是容易确定的。
于是我们考虑设 操作二完成之后的序列是 \(D_i\),那么最后的贡献就是:
所以考虑设计一种 dp:\(f_{i,j}\) 代表第 \(i\) 位上的 \(D_i\) 填了 \(j\) 的最优方案,则有如下转移:\(f_{i,j}=\min_{k\ge0}\{f_{i-1,k}+C\max(j-k,0)+|j-A_i|\}\)。于是最后的答案应该是 \(f_{n+1,0}\),初始状态 \(f_{0,0}=0\)。
不妨假设 \(f_{0,i}=(C+1)i\),这样只会从 \(f_{0,0}\) 处转移出来。这时候有一个重要的结论:\(f_{i,j}\) 是一个下凸函数(离散)。那么我们分析一下转移的状况。令 \(g_{i,j}=f_{i,j}-|j-A_i|\),我们作如下的归纳证明:
假设 \(f_{i-1,x_0}\) 是所有 \(f_{i-1,j}\) 中最小的,那么一定有 \(g_{i,k\le x_0}=f_{i-1,x_0}\);
假设 \(f_{i-1,x_1}-f_{i-1,x_1+1}>C\) 且是第一次 \(>C\),那么对于 \(x_0+1\le k \le x_1\) 有 \(g_{i,k}=f_{i-1,k}\);
最后对于 \(x_1+1\le k\),我们有 \(g_{i,k}=f_{i-1,x_1}+C(k-x_1)\)。
于是,我们发现 \(g_i\) 的斜率是:\(0\),\(f_{i-1}\) 的一段斜率且在 \([1,C-1]\) 内,\(C\)。根据归纳假设,\(g_i\) 是一个下凸函数,又因为 \(|j-A_i|\) 也是一个下凸函数,\(f_i\) 是一个下凸函数。
然而这个 dp 的过程依然难以计数。我们考虑转而去维护斜率,容易发现 \(g_i\) 中的斜率最多有 \([0,C]\) 这么多种(加入了 \(|j-A_i|\) 后,可能会出现 \(-1\) 和 \(C+1\)),于是我们考虑只维护每种斜率的分界点可重集 \(S\),初始化来说就是 \(C\) 个 \(0\)。考虑一下每次的操作:我们把 \(\leq A_i\) 的斜率 \(-1\),对 \(\ge A_i\) 的斜率 \(+1\),相当于放入两个 \(A_i\);然后计算答案,给答案加上 \(A_i-\min(S)\),这里是因为要转移到 \(f_{n+1,0}\),相当于每次选个最小值;最后把斜率中 \(-1\) 和 \(C+1\) 的部分删去,这相当于删去分界点的头尾,即可重集的最大值和最小值。
ok,解决了原问题,现在我们来考虑如何计数。我们容易发现我们实际上只用求出每个点被作为最小值删去了几次,我们记为 \(tot(x)\)。然后我们发现直接求出 \(tot(x)\) 不太容易,我们可以转而求小于 \(x\) 的数被删去了几次,最后再差分回来。具体地,因为只关心每个数是否小于 \(x\),我们只需要记 小于 \(x\) 的数为 \(0\),大于等于 \(x\) 的数为 \(1\),然后记 \(h_{i,j}\) 为刚加入两个 \(A_i\) 时有 \(j\) 个 \(1\) 的局面数量,你会发现只要不是有 \(C+2\) 个 \(1\),我们删去的最小值一定是 \(0\),然后就可以统计方案了。于是有:
最后答案即:
reference: https://kewth.github.io/2020/11/16/好题题解整理(四)/ kewth 的博客:好题题解整理