最长递增子序列的长度(LIS)使用线段树
段树是一种多功能的数据结构,旨在以对数时间复杂度回答范围查询和执行数组更新操作,其中每个节点存储与数组中特定范围的元素相关的信息。
在最长递增子序列(LIS)问题的背景下,需要确定给定序列中元素按递增顺序排序的最长子序列的长度,可以利用线段树来高效计算数组中最长递增子序列的长度。
这种方法与传统方法相比显着降低了时间复杂度,并在基因组学、自然语言处理和模式识别等领域有许多应用。本文探讨了段树的基本原理,并展示了它们在解决最长递增子序列问题中的潜力。
语法
Segment Tree build function −
void build(vector<int> &tree, const vector<int> &arr, int start, int end, int index) </int>
Segment Tree query function −
int query(const vector<int> &tree, int start, int end, int l, int r, int index)
段树更新函数 −
void update(vector<int> &tree, const vector<int> &arr, int start, int end, int pos, int value, int index)
算法
使用线段树找到最长递增子序列(LIS)的长度的算法如下 -
初始化表示输入序列的数组。
使用与输入序列相同大小的段树进行初始化
使用build函数构建线段树
处理输入序列的每个元素。
For each element, query the Segment Tree to find the maximum length of LIS ending at the current element.
Update the Segment Tree using the update function.
对输入序列中的所有元素重复执行步骤4-6。
The final answer is the maximum value stored in the Segment Tree.
Approach 1: Using simple Segment Tree
In this approach, we implement a simple Segment Tree without any optimization techniques such as lazy propagation.
Example-1
The program below demonstrates how to find the Length of Longest Increasing Subsequences (LIS) using a simple Segment Tree in C++. The build, query, and update functions are used to construct the Segment Tree, retrieve the maximum length of LIS ending at a specific element, and update the Segment Tree with new LIS lengths, respectively. The lengthOfLIS function iterates through each element in the input sequence and computes the LIS length using the Segment Tree.
#include <iostream> #include <vector> #include <algorithm> using namespace std; void build(vector<int> &tree, const vector<int> &arr, int start, int end, int index) { if (start == end) { tree[index] = arr[start]; } else { int mid = start + (end - start) / 2; build(tree, arr, start, mid, 2 * index + 1); build(tree, arr, mid + 1, end, 2 * index + 2); tree[index] = max(tree[2 * index + 1], tree[2 * index + 2]); } } int query(const vector<int> &tree, int start, int end, int l, int r, int index) { if (l <= start && end <= r) { return tree[index]; } if (end < l || r < start) { return 0; } int mid = start + (end - start) / 2; return max(query(tree, start, mid, l, r, 2 * index + 1), query(tree, mid + 1, end, l, r, 2 * index + 2)); } void update(vector<int> &tree, const vector<int> &arr, int start, int end, int pos, int value, int index) { if (pos < start || end < pos) { return; } if (start == end) { tree[index] = value; } else { int mid = start + (end - start) / 2; update(tree, arr, start, mid, pos, value, 2 * index + 1); update(tree, arr, mid + 1, end, pos, value, 2 * index + 2); tree[index] = max(tree[2 * index + 1], tree[2 * index + 2]); } } int lengthOfLIS(const vector<int> &nums) { int n = nums.size(); vector<int> arr(n, 0), tree(4 * n, 0); build(tree, arr, 0, n - 1, 0); for (int num : nums) { int lis_len = query(tree, 0, n - 1, 0, num - 1, 0) + 1; update(tree, arr, 0, n - 1, num, lis_len, 0); } return query(tree, 0, n - 1, 0, n - 1, 0); } int main() { vector<int> nums = {10, 9, 2, 5, 3, 7, 101, 18}; cout << "Length of Longest Increasing Subsequence: " <<lengthOfLIS(nums) << endl; return 0; }
输出
Length of Longest Increasing Subsequence: 3
使用带有延迟传播的段树的方法
In this approach, we implement a Segment Tree with lazy propagation to further optimize the time complexity of the algorithm.
Example 2
下面的代码演示了如何使用带有延迟传播的段树在C++中找到最长递增子序列(LIS)的长度。这段代码与方法1的代码相似,两种方法之间的主要区别在于段树的内部实现。懒惰传播技术在这段代码中没有明确显示,因为它优化了特定用例的更新函数,而这些用例在LIS问题中不存在。然而,代码的基本结构保持不变,并且构建、查询和更新函数的使用方式与方法1中的类似。
<int>#include <iostream> #include <vector> #include <algorithm> using namespace std; void build(vector<int> &tree, const vector<int> &arr, int start, int end, int index) { if (start == end) { tree[index] = arr[start]; } else { int mid = start + (end - start) / 2; build(tree, arr, start, mid, 2 * index + 1); build(tree, arr, mid + 1, end, 2 * index + 2); tree[index] = max(tree[2 * index + 1], tree[2 * index + 2]); } } int query(const vector<int> &tree, int start, int end, int l, int r, int index) { if (l <= start && end <= r) { return tree[index]; } if (end < l || r < start) { return 0; } int mid = start + (end - start) / 2; return max(query(tree, start, mid, l, r, 2 * index + 1), query(tree, mid + 1, end, l, r, 2 * index + 2)); } void update(vector<int> &tree, const vector<int> &arr, int start, int end, int pos, int value, int index) { if (pos < start || end < pos) { return; } if (start == end) { tree[index] = value; } else { int mid = start + (end - start) / 2; update(tree, arr, start, mid, pos, value, 2 * index + 1); update(tree, arr, mid + 1, end, pos, value, 2 * index + 2); tree[index] = max(tree[2 * index + 1], tree[2 * index + 2]); } } int lengthOfLIS(const vector<int> &nums) { int n = nums.size(); vector<int> arr(n, 0), tree(4 * n, 0); build(tree, arr, 0, n - 1, 0); for (int num : nums) { int lis_len = query(tree, 0, n - 1, 0, num - 1, 0) + 1; update(tree, arr, 0, n - 1, num, lis_len, 0); } return query(tree, 0, n - 1, 0, n - 1, 0); } int main() { vector<int> nums = {10, 9, 2, 5, 3, 7, 101, 18}; cout << "Length of Longest Increasing Subsequence: " << lengthOfLIS(nums) << endl; return 0; } </int>
输出
Length of Longest Increasing Subsequence: 3
Conclusion
在本文中,我们通过C++中的线段树技术来说明确定最长递增子序列(LIS)的范围的方法。我们阐述了两种方法:一种是直接执行线段树,另一种是利用延迟传播的改进方法。这两种技术在解决LIS问题上都很有效,而优化方法中的延迟传播进一步降低了时间复杂度。
以上是最长递增子序列的长度(LIS)使用线段树的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

PHP中数组的长度并没有固定的限制,它可以根据系统的内存大小来动态调整。在PHP中,数组是一种非常灵活的数据结构,可以存储任意数量的元素,每个元素可以是任意类型的值,甚至可以是另一个数组。PHP数组的长度限制主要取决于系统的内存大小和PHP配置的内存限制。一般来说,如果系统的内存足够大,并且PHP的内存限制足够高,数组的长度可以很大。但是,如果系统内存不足或

PHP数组长度是否受限制?需要具体代码示例在PHP中,数组长度并不受到固定的限制,可以根据系统内存的实际限制来动态调整数组大小。PHP中的数组是一种动态数组,因此可以根据需要动态增长或缩小。在PHP中,数组是一种有序映射的数据结构,可以用数组下标或关联数组的键值来访问数组元素。下面我们来看具体的代码示例来演示PHP数组长度是否受限制。首先,我们可以通过以下代

本文的目的是实现一个程序,以最大化给定数组中没有公共字符的一对字符串的长度总和。根据定义,字符串是字符的集合。问题陈述实现一个程序,以最大化给定数组中没有公共字符的一对字符串的长度总和。示例1LetusconsidertheInputarray:a[]=[“efgh”,“hat”,“fto”,“car”,“wxyz”,“fan”]Outputobtained:8说明字符串“abcd”和“wxyz”中没有共同字符。结果,两个字符串相加的长度为4+4,等于8,是所有可行对中最长的长度。示例2Letu

如何使用C++中的最长递增子序列算法,需要具体代码示例最长递增子序列(LongestIncreasingSubsequence,简称LIS)是一个经典的算法问题,其解决思路可以应用于多个领域,如数据处理、图论等。在本文中,我将为大家介绍如何使用C++中的最长递增子序列算法,并提供具体的代码示例。首先,我们来了解一下最长递增子序列的定义。给定一个序列a1,

len函数的作用与意义从不同角度解读len函数是Python编程语言中常用的函数之一。它主要用于返回一个容器对象(例如字符串、列表、元组等)的长度或元素个数。这个简单的函数在编写程序时起着非常重要的作用,有着多个角度可以解读其作用与意义。本文将从性能、可读性和容器类型的角度对len函数进行解读,并提供具体的代码示例。一、性能角度在处理大规模数据时,程序的性能

在golang中,验证输入文本的长度是一个常见的需求。通过验证,我们可以确保输入的文本符合特定的要求,并且长度在我们期望的范围内。在本文中,我们会探讨如何使用golang验证输入文本的长度。首先,我们需要了解一下golang中常用的字符串函数。其中,len()函数用于计算字符串的长度。例如,以下代码可以计算字符串"helloworld"的长度:str:=

斜边是指直角三角形中与直角相对的最长边。可以使用毕达哥拉斯定理找到斜边的长度。根据毕达哥拉斯定理,两条边长度的平方和等于第三条边长度的平方,即a2+b2=c2其中,a、b、c表示直角三角形的三条边。So,Hypotenuse=Math.sqrt(Math.pow(base,2)+Math.pow(height,2))在本文中,我们将看到如何使用Java编程语言找到斜边的长度。展示给你一些实例Instance-1的中文翻译为:实例-1假设底长和高分别为3和4。然后通过使用勾股定理公式,Length

在这个问题中,我们需要找到长度为K且正好包含K个元音的子串的总数。我们将看到解决问题的两种不同方法。我们可以使用一种简单的方法来检查每个长度为K的子串中元音的数量。此外,我们可以使用滑动窗口方法来解决该问题。问题陈述——我们给出了一个长度为N的字符串str,包含小写和大写字母字符。我们需要统计长度为K且正好包含X个元音的子串的总数。示例输入–str="TutorialsPoint",K=3,X=2输出–6解释–长度为3且恰好包含2个元音的子串是:'uto'、'ori'、'ri
