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;

}


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3、架构-事务处理

目录 概述 场景事例 本地事务 实现原子性和持久性 实现隔离性 概述 事务处理几乎在每一个信息系统中都会涉及&#xff0c;它存在的意义是为 了保证系统中所有的数据都是符合期望的&#xff0c;且相互关联的数据之间不 会产生矛盾&#xff0c;即数据状态的一致性&#xff0…

meshlab: pymeshlab合并多个物体模型并保存(flatten visible layers)

一、关于环境 请参考&#xff1a;pymeshlab遍历文件夹中模型、缩放并导出指定格式-CSDN博客 二、关于代码 本文所给出代码仅为参考&#xff0c;禁止转载和引用&#xff0c;仅供个人学习。 本文所给出的例子是https://download.csdn.net/download/weixin_42605076/89233917中的…

np.linalg.norm()

np.linalg.norm()是NumPy中用于计算向量或矩阵的范数的函数。它可以计算不同类型的范数&#xff0c;包括向量的L1范数、L2范数以及矩阵的Frobenius范数等。 基本用法如下, numpy.linalg.norm(x, ordNone, axisNone, keepdimsFalse) x&#xff1a;输入数组&#xff0c;可以是…

Python | Leetcode Python题解之第90题子集II

题目&#xff1a; 题解&#xff1a; class Solution:def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:if not nums:return list()results list()nums.sort()visited [False] * len(nums)self.dfs(nums, results, list(), visited, 0)return resultsdef df…

elasticsearch使用Ngram实现任意位数手机号搜索

文章目录 Ngram自定义分词案例实战问题拆解 Ngram分词器定义Ngram分词定义Ngram分词示例Ngram分词应用场景 Ngram分词实战 Ngram自定义分词案例 当对keyword类型的字段进行高亮查询时&#xff0c;若值为123asd456&#xff0c;查询sd4&#xff0c;则高亮结果是&#xff1c;em&a…

欧洲风景(地理)

1.尼斯湖 尼斯湖亦译内斯湖&#xff0c;位于英国苏格兰高原北部的大峡谷中&#xff0c;湖长39公里&#xff0c;宽2.4公里。面积并不大&#xff0c;却很深。传说这儿住着一只水怪&#xff0c;因此吸引了大量游客。 2.伦敦塔桥 伦敦塔桥是从英国伦敦泰晤士河口算起的第一座桥(泰…

类图及类的关系

类图&#xff08;Class Diagram&#xff09;是UML&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;中的一种图&#xff0c;用于描述系统中类的静态结构&#xff0c;包括类的属性、方法以及类之间的关系。 一、类 类&#xff08;Class&#xff09;…

Elasticsearch - HTTP

文章目录 安装基本语法索引创建索引查看索引删除索引 文档创建文档更新文档匹配查询多条件查询聚合查询映射 安装 https://www.elastic.co/downloads/past-releases/elasticsearch-7-17-0 下载完成启动bin/elasticsearch服务&#xff0c;可以在Postman调试各种请求。 基本语法…

数据库系统概论(超详解!!!)第八节 数据库设计

1.数据库设计概述 数据库设计是指对于一个给定的应用环境&#xff0c;构造&#xff08;设计&#xff09;优化的数据库逻辑模式和物理结构&#xff0c;并据此建立数据库及其应用系统&#xff0c;使之能够有效地存储和管理数据&#xff0c;满足各种用户的应用需求&#xff0c;包…

【Qt问题】windeployqt如何提取Qt依赖库

往期回顾 【Qt问题】Qt Creator 如何链接第三方库-CSDN博客 【Qt问题】Qt 如何带参数启动外部进程-CSDN博客 【Qt问题】VS2019 Qt win32项目如何添加x64编译方式-CSDN博客 【Qt问题】windeployqt如何提取Qt依赖库 考虑这个问题主要是&#xff1a;当我们的程序运行好之后&#…

Nginx生产环境最佳实践之配置灰度环境

你好呀&#xff0c;我是赵兴晨&#xff0c;文科程序员。 下面的内容可以说是干货满满建议先收藏再慢慢细品。 今天&#xff0c;我想与大家深入探讨一个我们日常工作中不可或缺的话题——灰度环境。你是否在工作中使用过灰度环境&#xff1f;如果是&#xff0c;你的使用体验如…

数据结构与算法===优先队列

文章目录 前言一、优先队列二、应用场景三、代码实现总结 前言 之前写过很多数据结构与算法相关的了&#xff0c;今天看一个新的数据结构&#xff0c;优先队列。优先队列类似队列&#xff0c;却又优先于队列&#xff0c;是堆实现的。接下来详细看看。 一、优先队列 优先队列一…

STL库简介

一、STL库的概念 STL&#xff1a;是C标准库的重要追组成部分&#xff0c;不仅是一个可以复用的组件库&#xff0c;而且还是一个包含了数据结构和算法的软件框架。 二、STL的版本 原始版本 Alexander Stepanov、 Meng Lee 在惠普实验室完成的原始版本&#xff0c; 是一个开源…

C语言错题本之<结构体>

以下叙述中正确的是________. A)预处理命令行必须位于源文件的开头 B)在源文件的一行上可以有多条预处理命令 C)宏名必须用大写字母表示 D)宏替换不占用程序的运行时间 答案&#xff1a;D 解析&#xff1a; A&#xff1a;在C、C等编程语言中&#xff0c;预处理指令&#xff08;…

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

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

RS编码和卷积码总结

RS编码 简要介绍RS编码及其原理 1. RS编码简介 Reed-Solomon编码&#xff08;RS编码&#xff09;是一种强大的纠错码&#xff0c;广泛应用于数据存储和传输中。RS编码由Irving S. Reed和Gustave Solomon于1960年提出&#xff0c;属于BCH码的一种&#xff0c;是基于有限域&am…

杨校老师项目之基于单片机STC89C52的智能环境监测系统【嵌入式】

获取全套资料&#xff1a; 有偿获取&#xff1a;mryang511688 技术&#xff1a;C语言、单片机等 摘要&#xff1a; 此设计可分为三个主要部分。此中的温度和湿度的检测功能&#xff0c;通过操纵单总线型温湿度传感器DHT11以数字形式显示&#xff0c;实现了切确测得温湿度的功能…

五分钟“手撕”时间复杂度与空间复杂度

目录 一、算法效率 什么是算法 如何衡量一个算法的好坏 算法效率 二、时间复杂度 时间复杂度的概念 大O的渐进表示法 推导大O阶方法 常见时间复杂度计算举例 三、空间复杂度 常见时间复杂度计算举例 一、算法效率 什么是算法 算法(Algorithm)&#xff1a;就是定…

蓝桥杯单片机之模块代码《串口发数据》

过往历程 历程1&#xff1a;秒表 历程2&#xff1a;按键显示时钟 历程3&#xff1a;列矩阵按键显示时钟 历程4&#xff1a;行矩阵按键显示时钟 历程5&#xff1a;新DS1302 历程6&#xff1a;小数点精确后两位ds18b20 历程7&#xff1a;35定时器测量频率 历程8&#xff…

队列的讲解

队列的概念 队列:只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头 一端进另一端出 也就是可以做到&#xff0c;先…