Dilworth定理:最少的下降序列个数就等于整个序列最长上升子序列的长度

概念如下:

狄尔沃斯定理_百度百科 (baidu.com)

本质就是找要求序列中最长的单调的子序列(不一定连续)的长度。


模板如下:

时间复杂度为O(N^2)

#include<iostream>using namespace std;int dp[100005],a[100005],n,maxx=-999;//dp[i]记录以i结尾的最长上升子序列int main(){cin>>n;for(int i=1;i<=n;i++) cin>>a[i],dp[i]=1;for(int i=1;i<=n;i++){for(int j=1;j<i;j++){if(a[i]>a[j]) dp[i]=max(dp[i],dp[j]+1);}maxx=max(maxx,dp[i]);                  }cout<<maxx;return 0;}

代码优化:

举个例子:

现在有序列4,8,9,5,6,7,2,7求LIS。

一个一个元素来看,首先无疑dp[1]=4 ,然后考察8,8>4,故把8加入尾部。然后9>8,也进入尾部,这时dp数组是{4, 8, 9}。

下一个元素是5,5<9,不能塞入尾部。我们找到第一个大于等于5的元素,是8。4->8是长度为2的上升子序列,4->5也是,但是5比8更小,所以更有潜力更新后面的子序列。所以把8换成5,现在DP是{4, 5, 9}。同样的道理DP又变成{4, 5, 6}。

现在我们尝到甜头了,因为下一个元素是7,本来是没有机会进入序列的,现在却可以了。于是dp变成{4, 5, 6, 7}。注意,显然DP是递增的(两种转移都不会破坏递增性),但这并不意味着它就是所求的上升子序列,你看,下一个元素是2,它会把dp更新成{2, 5, 6, 7},但原序列并没有一个子序列是{2, 5, 6, 7}。

最后剩一个元素7,由于我们在求严格上升的子序列,不能将它插入尾部,于是我们把7替换成7——这个元素对子序列长度没有贡献。好了,最后得到的数组长度是4,所以最长上升子序列的长度就是4 。

刚刚提到,dp是递增的,所以我们不用每次都扫描一遍数组, 而可以进行二分查找。这样,就把复杂度降到了 𝑂(𝑛log⁡𝑛) ,具体地,代码如下

int len = 0;
for (int i = 0; i < n; ++i)
{if (dp[len] < A[i])dp[++len] = A[i];else*lower_bound(dp + 1, dp + len + 1, A[i]) = A[i];
}

题目如下:

1、我最喜欢吃饭了

把n个人提出来成为原序列的一个子序列,根据题意这个子序列中的元素是单调递增的(即后一项总是大于前一项),我们称为单调递增子序列。本问所求n个人顺序最多需要需要多少个窗口,即求最长的单调递增子序列数目。

#include <iostream>
#include <algorithm>
using namespace std;
int a[5005], dp[5005]; int main()
{int n, m;cin >> n >> m;// n个人m个窗口for (int i = 1; i <= n; i++) cin >> a[i],dp[i] = 1; //初始化int cnt = 1;for (int i = 1; i <= n; i++){for (int j = 1; j < i; j++){if (a[i] <= a[j]) dp[i] = max(dp[i], dp[j] + 1);}cnt = max(cnt, dp[i]);}if (cnt > m)cout << "Karashi lovelove" << endl;//非法else cout << "Karashi cblcd" << endl;//合法return 0;
}

代码优化

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int a[5005], dp[5005];int main()
{int n, m;cin >> n >> m;// n个人m个窗口for (int i = 0; i < n; i++) cin >> a[i];int len = 0;memset(dp, 127, sizeof(dp));for (int i = 0; i < n; i++){if (dp[len] >= a[i]) dp[++len] = a[i];else *upper_bound(dp + 1, dp + len + 1, a[i], greater<int>()) = a[i];}//cout << len << endl;if (len > m)cout << "Karashi lovelove" << endl;//非法else cout << "Karashi cblcd" << endl;//合法return 0;
}

2、木棍加工

思路:

1、先对宽度进行排序,然后对宽度相同的进行长度排序;大的在前,小的在后

2、然后对已经排好的数组,统计最长连续单调递减子序列数目即可。

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 5010;
int f[N];struct Data
{int l, w;
}a[N];bool cmp(Data a,Data b) //先排序宽度,再排序长度
{if (a.w != b.w) return a.w > b.w;return a.l > b.l;
}int main()
{int n;cin >> n ;for (int i = 1; i <= n; i++){cin >> a[i].l >> a[i].w;f[i] = 1; //初始化}int cnt = 1;sort(a + 1, a + n + 1, cmp);for (int i = 1; i <= n; i++) //后者与前者比长度{for (int j = 1; j < i; j++){if (a[i].l > a[j].l) f[i] = max(f[i], f[j] + 1);}cnt = max(cnt, f[i]);}cout << cnt << endl;return 0;
}

3、导弹拦截

典型上述题型,但是下面会超时,因此我们要用到二分查找

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e4 + 10;
int dp1[N],a[N],dp2[N];int main()
{int n = 0;while (cin >> a[n]) {n++;}int mx1 = 0, mx2 = 0;for (int i = 0; i < n; i++){dp1[i] = 1, dp2[i] = 1;for (int j = 0; j < i; j++){if (a[j] < a[i])  dp1[i] = max(dp1[i], dp1[j] + 1);if (a[j] >= a[i]) dp2[i] = max(dp2[i], dp2[j] + 1);} mx1 = max(mx1, dp1[i]); //最长单调连续递增子序列mx2 = max(mx2, dp2[i]); //最长单调连续递减子序列}cout << mx2 << endl;cout << mx1 << endl;return 0;
}

变量声明:

数组 a 存储从输入数据;
数组 dp 存储最长不上升子序列;
变量 len 代表 dp 的结尾位置(即最长不上升子序列的长度)。


把 a 中的每个元素挨个放到 dp 里:

  • 如果 a[i] ​≤ dp​[len],说明 ai​ 可以直接加入 dp(而整个 dp 数组还是有序的);

  • 如果 a[i]​ > dp[len]​,说明若放入 a[i]​ 则 dp 会无序,所以要找办法把 a[i]​ 放进去:

怎么放呢?在 dp 中找到第一个小于 a[i]​ 的数,用 a [i]​ 代替它。
找到第一个小于 a[i]​ 的数,使用 upper_bound 可以在 O(logn) 复杂度内找到(需要改比较器)。

由于它返回的是指针就可以有一些奇特操作。

*upper_bound(dp + 1, dp + len + 1, A[i], greater<int>()) = A[i];

*lower_bound(dp + 1, dp + len + 1, a[i]) = a[i];

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int dp[N],a[N];int main()
{int n = 0, len = 0;while (cin >> a[n]) {n++;}memset(dp, 127, sizeof(dp));for (int i = 0; i < n; i++){if (dp[len] >= a[i]) dp[++len] = a[i];else *upper_bound(dp + 1, dp + len + 1, a[i], greater<int>()) = a[i];}cout << len << endl;len = 0;memset(dp, 0, sizeof(dp));for (int i = 0; i < n; ++i){if (dp[len] < a[i])dp[++len] = a[i];else*lower_bound(dp + 1, dp + len + 1, a[i]) = a[i];}cout << len << endl;return 0;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/701982.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

物联网应用开发--STM32与新大陆云平台通信(云平台控制蜂鸣器、LED)

实现目标 1、掌握云平台执行器的创建 2、熟悉STM32 与ESP8266模块之间的通信 3、具体实现目标&#xff1a;&#xff08;1&#xff09;创建5个执行器&#xff1a;蜂鸣器&#xff0c;LED1&#xff0c;LED2&#xff0c;ED3&#xff0c;LED4;&#xff08;2&#xff09;执行器能对…

RK3568平台开发系列讲解(SPI篇)SPI数据的传输

🚀返回专栏总目录 文章目录 一、数据结构1.1、spi_transfer 结构体1.2、spi_message二、数据发送程序分析沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 参考资料: spi_transferspi_message一、数据结构 spi 数据传输主要使用了 spi_message 和 spi_transfer 结构…

Spring AOP(概念,使用)

目录 Spring AOPAOP是什么什么是Spring AOPAOP实际开发流程1. 引入依赖2. 编写AOP程序 Spring AOP详解Spring AOP中的核心概念Spring AOP的通知类型六种类型PointCutOrder(切面优先级) Spring AOP AOP是什么 Aspect Oriented Programminig(面向切面编程)切面指的是某一类特定…

cpu缓存一致性问题---cache写策略

为什么会有cpu缓存一致性问题&#xff1f; cpu缓存一致性指的&#xff1a;是缓存中和所其对应在主存中的数据的一致性。 因为cpu运算产生新数据后基于写回策略只更新缓存的值会导致缓存和主存不一致问题 解决cpu缓存一致性问题前&#xff0c;先了解写回策略是什么 了解写回策…

R语言基础--文件读写

From生物技能树&#xff08;R第五节&#xff09; 文章目录 一、文件读写1.注意用project管理工作目录2、文件读取1、读取.txt文件2、读取.csv文件注意&#xff1a;数据框不允许重复的行名 3.数据框的导出4.读取文件的其他方式(用于读取/导出文件的R包)--经验1.base2.readr3.dat…

[初学者来练]用html+css+javascript个人博客作业需求

文章目录 项目概述项目需求页面设计主页文章列表页文章详情页用户交互额外功能&#xff08;可选&#xff09; 技术要求提交要求评分标准文件代码格式提示HTML 页面结构CSS 样式设计JavaScript 交互功能 项目概述 这个项目旨在通过使用HTML、CSS和JavaScript创建一个简单而功能…

使用docker创建hadoop集群:Couldn‘t upload the file

运行的环境; Windows10 Docker Desktopdocker-hadoop 出现的问题如下: 解决方法 https://github.com/big-data-europe/docker-hadoop/issues/98

秋招算法——背包模型——423采药问题——模板:背包问题

文章目录 题目描述思路分析实现代码分析总结 题目描述 思路分析 这里明显是使用背包问题&#xff0c;所以这里参考一下背包这个模板题的内容这个是朴素版的模板&#xff0c;没有经过代码的优化 #include <iostream> #include <algorithm>using namespace std;con…

数据库SQL编写规范-SQL书写规范整理(SQL语句书写规范全解-Word原件)

编写本文档的目的是保证在开发过程中产出高效、格式统一、易阅读、易维护的SQL代码。 1 编写目 2 SQL书写规范 3 SQL编写原则 软件全套精华资料包清单部分文件列表&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说…

企业如何利用美国多IP服务器来提升网站的安全性?

企业如何利用美国多IP服务器来提升网站的安全性? 在当前网络环境下&#xff0c;网站安全性日益成为企业面临的重要挑战。为了有效应对各种潜在威胁&#xff0c;越来越多的企业选择利用美国多IP服务器来提升其网站的安全性。这种服务器配置能够通过一系列策略来增加网站的安全…

【PB案例学习笔记】-02 目录浏览器

写在前面 这是PB案例学习笔记系列文章的第二篇&#xff0c;该系列文章适合具有一定PB基础的读者&#xff0c; 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上…

学习Uni-app开发小程序Day11

今天是学习的第11天&#xff0c;今天学习了组件的生命周期&#xff0c;这里的生命周期&#xff0c;主要是学习uni-app的组件生命周期&#xff0c;虽然vue也有&#xff0c;但主要还是学习uni-app的。1. onLoad 监听页面加载&#xff0c;该钩子被调用时&#xff0c;响应式数据、计…