2021.12.06 P2501 [HAOI2006]数字序列(动态规划+LIS)

https://www.luogu.com.cn/problem/P2501

题意:

现在我们有一个长度为 n 的整数序列 a。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。

求最小的改变次数和此时每个数改变的绝对值之和。

分析:

对于 \(a_i\) ,\(a_j\) , \(i<j\) ,当 \(j-i<=a_j-a_i\) 时 \(i\) 与 \(j\) 这两项保留。移项得: \(a_i-i<=a_j-j\) ,则第一问转变为求 \(a_i-i\) 的最长不降子序列。在求出来的最长不降子序列中任意相邻两个元素之间的原序列 \(b_i\) 的元素均不在 \(b_k\) 到 \(b_{k+1}\) 中。任取原序列中的 \(k\) ,使 \(i<=k\) 且 \(k<=j\) ,\(suf\) 为从 \(k+1\) 开始到 \(j\) 之间修改的绝对值之和,这些数均被修改为 \(a_j\) , \(pre\) 为从 \(i\) 开始到 \(k\) 之间修改的绝对值之和,这些数均被修改为 \(a_i\) 。如果存在一个数 \(a_x\) ,且 \(a_x>a_j\) ,则这个数最大可被被修改为 \(a_j\) ,同理,如果存在一个数 \(a_y\) ,且 \(a_y<a_i\) ,那么把 \(a_y\) 修改成 \(a_i\) 更优。但是要保证原序列被修改后依旧是最长不降,所以一定存在某个点使 \(i\) 到 \(j\) 这个区间被分割后形成两层楼梯阶梯,使得修改的绝对值最小。

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; #define int long long
const int N=4e4+10;
const int inf=0x3f3f3f3f;
int n,a[N],f[N],pre[N],suf[N],fin[N],top,len[N];
int cnt,head[N];
struct node{
int to,next;
}e[N]; inline void add(int u,int v){
++cnt;
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
} signed main(){
IOS;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],a[i]-=i;
a[0]=-inf;a[n+1]=inf;
for(int i=1;i<=n+1;i++){
int L=0,R=top;
while(L<R){
int mid=(L+R+1)>>1;
if(fin[mid]<=a[i])L=mid;
else R=mid-1;
}
if(L==top)++top;
len[i]=L+1;
fin[L+1]=a[i];
add(len[i],i);
}
add(0,0);
memset(f,inf,sizeof(f));
f[0]=0;
for(int i=1;i<=n+1;i++){
for(int j=head[len[i]-1];j;j=e[j].next){
int v=e[j].to;
if(v>i||a[v]>a[i])continue;
pre[v]=suf[i-1]=0;
for(int k=v+1;k<i;k++)pre[k]=pre[k-1]+abs(a[k]-a[v]);
for(int k=i-2;k>=v;k--)suf[k]=suf[k+1]+abs(a[k+1]-a[i]);
for(int k=v;k<i;k++)f[i]=min(f[i],f[v]+suf[k]+pre[k]);
}
}
cout<<n-top+1<<endl<<f[n+1];
return 0;
}

最新文章

  1. 使控件具有 Tilt 效果
  2. 汉字正则表达式[\u4E00-\u9FFF]原因
  3. 编写Redis启停服务脚本
  4. 20145222黄亚奇《Java程序设计》第10周学习总结
  5. jq获取元素到底部的距离
  6. WCF存储图片到指定文件夹下
  7. Java中Thread类的start()和run()的区别
  8. (二)backbone - DEMO - user list
  9. UIP协议栈
  10. ConcurrentModificationException异常解决办法
  11. teamviewer无法启动
  12. Drools学习笔记-01-在eclipse indgo集成Drools5.5
  13. java.lang.ClassNotFoundException: org.apache.lucene.store.Directory
  14. Matlab生成.exe可执行程序
  15. 2017-2018-1 1623 bug终结者 冲刺004
  16. PySide中QtGui.QFrame的用法
  17. 目标检测之faster-RCNN和FPN
  18. jdk8+Mybatis3.5.0+Mysql读取LongBlob失败
  19. 运行Maven工程中修改tomcat端口
  20. Spring 注解bean默认名称规则

热门文章

  1. DDOS防御实验----反射器的安全配置
  2. Go 语言 切片的使用(增删改查)
  3. 半吊子菜鸟学Web开发 -- PHP学习2-正则,cookie和session
  4. class文件和java文件区别
  5. JavaScript的一些实用操作(逐步添加)
  6. Oracle入门基础(十一)一一PL/SQL基本语法
  7. CHAR 和 VARCHAR 的区别?
  8. java-注解相关
  9. springboot使用策略模式实现一个基本的促销
  10. 运筹学之&quot;简单平均预测法&quot;和&quot;加权滑动平均预测法&quot;和&quot;确定平滑系数&quot;