数字序列

首先来看一下蓝书上面的两个思考题

一.

将一个序列A改成单调不下降序列,最少需要修改多少个数?

答:用A的长度减去其最长单调不下降子序列的长度即可

那如果在最少修改数的基础上,我要让每个数改变的绝对值之和的最小值最小怎么办?

答:首先,这根“Making the Grade”这道题目很像,所以我们考虑用DP

我们假设已经选好了一个A的最长单调不下降子序列作为其保留的数,然后把剩下的数进行修改

由“分级”这一道题目给我们带来的启发,我们可以想到一个引理:设a[i]a[j]是我们选出的A的最长单调不下降子序列中相邻的两个数(在原序列A中不一定相邻),那么我们修改a[i]a[j]中间的数时,可以找到一个分界点k,让a[i+1~k]的值全部修改为a[i]a[k+1~j]的值全部修改为a[j]

这个证明与AcWing上y总的证明以及我的写在博客里面的证明非常像:我们假设已经随便移动这些数让他们介于了a[i]a[j]之间

这里借用洛谷的一个图片,实际上这些平台根本不用递增

然后我们依次从左往右考虑每一个平台,让他往上或者往下移动,如果中途碰到了另一个平台就带着这个平台一起移动(但是方向一定要最优),由于平台个数是有限的,最终一定会移动完成的,也就是引理

注意,上述移动过程的正确性还要基于我们选出的是最长不下降子序列,也就意味着b[i+1]b[j1]的每一个数要么小于b[i],要么大于b[j],所以一个平台在碰到其他平台之前的移动过程中,不会出现最优方向改变的情况(i.e.,比如不会说本来最开始向下移动最优,但是动着动着就在还没有碰到其他平台的地方最优方向改变,变成向上移动最优了)

但是还有一个问题:A可能会有多个最长单调不下降子序列,我们怎么确定选择哪一个?

实际上,这种情况有大概两种解决方法:第一种是尝试证明无论怎么选答案都一样,就随便选一个就可以了;第二种就是利用DP或者贪心等等选择最优方案

这里不用第一种,因为这是伪命题,所以用第二种

我们设f[i]表示以a[i]结尾的最长单调不下降子序列的长度,G[i]是一个向量,存储所有长度为i的LIS的结尾的下标(i.e.,对于G[i][j],存在一个上升子序列,使得其长度为i且以a[G[i][j]]结尾)

然后我们枚举每一个i的时候,再枚举G[f[i]1],判断一下相对大小,然后在枚举分段点即可

时间复杂度O(n3)

但是数据是随机生成的,说这句话的意思就是说时间复杂度大点点没事(这也就是为什么我们要用G去维护信息而不是直接再枚举一维,如果再枚举的话时间复杂度就跟数据无关了,直接爆炸)

另外提一句,这道题目还可以用可并堆“左偏树”解决

二.

将一个序列A改成单调上升序列,最少需要修改多少个数?

答:设b[i]=a[i]i,用B的长度减去其最长单调不下降子序列的长度即可

那如果在最少修改数的基础上,我要让每个数改变的绝对值之和的最小值最小怎么办?

答:修改a[i],那么对应的b[i]也会被修改,而且由于i不变,两者的修改一模一样,所以转化成了上一个问题

这也就是这道题目的做法

posted @   最爱丁珰  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示