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;
}

2021.12.06 P2501 [HAOI2006]数字序列(动态规划+LIS)的更多相关文章

  1. P2501 [HAOI2006]数字序列 (LIS,DP)(未完成)

    第二问好迷... #include "Head.cpp" #include <vector> const int N = 35007; vector<int> ...

  2. 洛谷 P2501 [HAOI2006]数字序列 解题报告

    P2501 [HAOI2006]数字序列 题目描述 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. ...

  3. 2021.12.06 P2511 [HAOI2008]木棍分割(动态规划)

    2021.12.06 P2511 [HAOI2008]木棍分割(动态规划) https://www.luogu.com.cn/problem/P2511 题意: 有n根木棍, 第i根木棍的长度为 \( ...

  4. 【BZOJ 1049】 1049: [HAOI2006]数字序列 (LIS+动态规划)

    1049: [HAOI2006]数字序列 Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变 ...

  5. Luogu P2501 [HAOI2006]数字序列

    题目 首先把\(a\)改成严格单调上升等于把\(a_i-i\)改成单调不降. 那么第一问可以直接做LIS,答案就是\(n-\)LIS的长度. 同时我们记录一下序列中每个位置结尾的LIS长度. 第二问我 ...

  6. p2501 [HAOI2006]数字序列

    传送门 分析 https://www.luogu.org/blog/FlierKing/solution-p2501 对于第二问的感性理解就是有上下两条线,一些点在上面的线的上面或者下面的线的下面,然 ...

  7. 【BZOJ】1049: [HAOI2006]数字序列(lis+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1049 题意:给一个长度为n的整数序列.把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希 ...

  8. 【BZOJ1049】 [HAOI2006]数字序列

    BZOJ1049 [HAOI2006]数字序列 dp好题? 第一问 第一问我会做!令\(b_i=a_i-i\),求一个最长不下降子序列. \(n-ans\)就是最终的答案. 第二问 好难啊.不会.挖坑 ...

  9. bzoj 1049 [HAOI2006]数字序列

    [bzoj1049][HAOI2006]数字序列 Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不 ...

随机推荐

  1. Rafy 框架:领域控制器

    本文简要说明如何使用 Rafy 框架中的领域控制器. 简介 领域控制器是 Rafy 框架中用于封装领域逻辑的主要方式. 在控制器中,开发者可以封装大量的业务逻辑,并向外暴露业务接口.内部的逻辑在实现时 ...

  2. Redis运维实战之集群中的脑裂

    1.对于分布式Redis主从集群来说,什么是脑裂? 所谓的脑裂,就是指在主从集群中,同时有两个主节点,它们都能接收写请求.而脑裂最直接的影响,就是客户端不知道应该往哪个主节点写入数据,结果就是不同的客 ...

  3. ctf之Flask_fileUpload

    启动环境,显示如图: 直接f12产看源码信息: 大致意思是:使用python编写文件然后以图片格式上传系统会以ipython格式解析,就可获取flag. 编写python代码: import os o ...

  4. docker专题 从入门到放弃

    1.docker是什么 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚 ...

  5. 如何处理异形屏iphone X?

    safe area: 默认放置在安全区域以避免遮挡, 但会压缩 在meta中添加viewport-fit=cover: 告诉浏览器要讲整个页面渲染到浏览器中,不管设备是圆角与否,这个时候会造成页面的元 ...

  6. InnoDB中加锁?

    InnoDB 实现了两种类型的行锁,共享锁(S)与排他锁(X).然后由于 InnoDB引擎又支持表级锁,所以它内部又有意向共享锁(IS)与意向排他锁(IX).这两种表锁,都是InnoDB内部自动处理, ...

  7. 下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d"?

    对于如下代码: String s1 = "a"; String s2 = s1 + "b"; String s3 = "a" + " ...

  8. Kafka 判断一个节点是否还活着有那两个条件?

    (1)节点必须可以维护和 ZooKeeper 的连接,Zookeeper 通过心跳机制检查每 个节点的连接 (2)如果节点是个 follower,他必须能及时的同步 leader 的写操作,延时不能太 ...

  9. Kafka 分区的目的?

    分区对于 Kafka 集群的好处是:实现负载均衡.分区对于消费者来说,可以提高并发度,提高效率.

  10. 汽车中的V流程开发

    各步骤的简介各步骤的简介 (1)Control Design and offline Simulation:算法模型构建和离线仿真(基于模型的设计).算法工程师用Matlab模型实现算法:并实施离线仿 ...