• 【AGC049E】Increment Decrement


    AGC049E Increment Decrement

    Solution

    以前很少做 atcoder 的题,今天一做,果然难炸了。

    哦,我做了不止一天啊,那没事了(主要自己又懒又菜

    首先我们考虑单一序列咋做。先转化为初始序列为 \(\{0\}\),我们要转成 \(\{A_i\}\)

    对于单一序列,假如我们知道了所有操作二完成之后的序列,贡献是容易确定的。

    于是我们考虑设 操作二完成之后的序列是 \(D_i\),那么最后的贡献就是:

    \[\sum_{i=1}^n C \max(D_{i}-D_{i-1},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\),然后就可以统计方案了。于是有:

    \[\sum_{i=0}^{x-1} tot(i)=K^n-\sum_{i=1}^n h_{i,C+2} \]

    最后答案即:

    \[\sum_{i=1}^n\sum_{j=1}^K (K^{n-1}-tot(B_{i,j}))B_{i,j} \]

    reference: https://kewth.github.io/2020/11/16/好题题解整理(四)/ kewth 的博客:好题题解整理

  • 相关阅读:
    JAVA多线程知识点
    RabbitMQ和Springboot集成RabbitMQ知识点
    JAVA动态代理cglib或jdk
    [转]解决System.Data.SqlClient.SqlException (0x80131904): Timeout 时间已到的问题的一个方向
    [转]C#判断文档编码格式,并读取文档数据(防止出现乱码)
    create_linux命令写入到sh脚本并删除
    cmd cd切换到d盘
    sql 优化前后
    LISTAGG()WITHIN GROUP()
    使用shell递归遍历文件并打印所有文件名的绝对路径
  • 原文地址:https://www.cnblogs.com/youddjxd/p/16065666.html
Copyright © 2020-2023  润新知