1、二维最长上升子序列 —— 相等可嵌套
(1)排序,一维正排序,二维正排序;
(2)对第二维度,求 最长 弱上升子序列,upper_bound
#include <iostream>
#include <vector>
#include <algorithm> //sort、max
using namespace std;
bool cmp(vector<int> &num1, vector<int> &num2)
{
if (num1[0] != num2[0]) return num1[0] < num2[0]; // 一维正排
else return num1[1] < num2[1]; // 弱上升,二维正排
}
/*
输入
5
2 2
2 4
3 3
2 5
4 5
输出
4
输入
2
2 2
3 2
输出
2
*/
int main()
{
int n;
cin >> n;
if (n <= 1)
{
cout << n;
return 0;
}
//上升排序
vector<vector<int>> num(n, vector<int>(2));
for (int i = 0; i < n; i++)
{
cin >> num[i][0] >> num[i][1];
}
sort(num.begin(), num.end(), cmp); //
//二分查找,N*log(N)
vector<int> temp;
temp.push_back(num[0][1]);
int len = 1;
for (int i = 1; i < n; i++)
{
auto it = upper_bound(temp.begin(), temp.end(), num[i][1]); // 弱上升,可重复
if (it == temp.end()) //查找不到,追加
{
temp.push_back(num[i][1]);
len++;
}
else //查找到,替换
{
*it = num[i][1];
}
}
cout << len;
return 0;
}
2、二维最长上升子序列 —— 相等不可嵌套
(1)排序,一维正排序,二维逆排序;
(2)对第二维度,求 最长 严格上升子序列,lower_bound
#include <iostream>
#include <vector>
#include <algorithm> //sort、max
using namespace std;
bool cmp(vector<int> &num1, vector<int> &num2)
{
if (num1[0] != num2[0]) return num1[0] < num2[0]; // 第一维正着排列
else return num1[1] > num2[1]; // 严格上升,第二维倒着排列
}
/*
输入
5
2 2
2 4
3 3
2 5
4 5
输出
3
输入
2
2 2
3 2
输出
1
*/
int main()
{
int n;
cin >> n;
if (n <= 1)
{
cout << n;
return 0;
}
//上升排序
vector<vector<int>> num(n, vector<int>(2));
for (int i = 0; i < n; i++)
{
cin >> num[i][0] >> num[i][1];
}
sort(num.begin(), num.end(), cmp); //
//二分查找,N*log(N)
vector<int> temp;
temp.push_back(num[0][1]);
int len = 1;
for (int i = 1; i < n; i++)
{
auto it = lower_bound(temp.begin(), temp.end(), num[i][1]); // 严格上升,无重复
if (it == temp.end()) //查找不到,追加
{
temp.push_back(num[i][1]);
len++;
}
else //查找到,替换
{
*it = num[i][1];
}
}
cout << len;
return 0;
}