//之前upper_bound lower_bound搞错了
// upper_bound( first, last, & val)算法返回一个非递减序列[first, last)中第一个 大于 val的地址。
// lower_bound( first, last, & val)算法返回一个非递减序列[first, last)中第一个 大于等于 值val的地址。
// upper_bound( first, last, & val, greater())算法返回一个非递增序列[first, last)中第一个 小于 val的地址。
// lower_bound( first, last, & val, greater())算法返回一个非递增序列[first, last)中第一个 小于等于 值val的地址。
// int pos = lower_bound(age.rbegin(), age.rend(), a[i]) - age.rbegin();
//rbegin rend反向迭代器(倒着查找)
1、把数组复制后排序,然后求其与原数组的LCS
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 10005;
int a[MAXN], b[MAXN];
int dp[2][MAXN];
int n, m;
void lcs() {
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (a[i] == b[j]) {
dp[i % 2][j] = dp[!(i % 2)][j - 1] + 1;
} else {
dp[i % 2][j] = max(dp[!(i % 2)][j], dp[i % 2][j - 1]);
}
}
}
}
void lis() {
for (int i = 1; i <= n; i++)
b[i] = a[i];
sort(b + 1, b + n + 1);
lcs();
cout << dp[n % 2][n] << endl;
}
//空间复杂度太大,重建有点难
int main() {
#ifdef LOCAL
freopen("zz_in.txt", "r", stdin);
freopen("zz_op.txt", "w", stdout);
#endif
while (cin >> n) {
for (int i = 1; i <= n; i++)
cin >> a[i];
lis();
}
#ifdef LOCAL
printf("Time used = %.2f\n", (double) clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
2、一维数组dp(可回溯,时间复杂度O(n^2))
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 10005;
int a[MAXN];
int dp[MAXN];
int from[MAXN]; //重建最优解用
stack<int> rb;
int n, m, ans_index;
//递增子序列!=连续递增子序列
int lis() {
int ans = 0;
ans_index = 0;
memset(dp, 0, sizeof(dp));
memset(from, 0, sizeof(from));
for (int i = 1; i <= n; i++) {
int tmp = 0;
for (int j = 1; j < i; j++) {
if (a[i] > a[j] && dp[j] > tmp) {
tmp = dp[j];
from[i] = j;
}
}
dp[i] = tmp + 1;
if (dp[i] > ans) {
ans = dp[i];
ans_index = i;
}
}
return ans;
}
void rebuild() {
while (from[ans_index] != 0) {
rb.push(a[ans_index]);
ans_index = from[ans_index];
}
rb.push(a[ans_index]);
while (!rb.empty()) {
cout << rb.top() << " ";
rb.pop(); //忘了pop导致死循环
}
cout << endl;
}
int main() {
#ifdef LOCAL
freopen("zz_in.txt", "r", stdin);
freopen("zz_op.txt", "w", stdout);
#endif
while (cin >> n) {
for (int i = 1; i <= n; i++)
cin >> a[i];
cout << lis() << endl;
}
#ifdef LOCAL
printf("Time used = %.2f\n", (double) clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
3、最快的办法(O(nlogn))
不太好回溯
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 10005;
int n, m;
int a[MAXN];
int b[MAXN];
// lower_bound() upper_bound()使用方法
int lis() {
memset(b, 0, sizeof(b));
int len = 1;
b[1] = a[1];
for (int i = 2; i <= n; i++) {
if (a[i] > b[len])
b[++len] = a[i];
else {
int j = lower_bound(b + 1, b + len + 1, a[i]) - b;
b[j] = a[i];
}
}
return len;
}
int main() {
#ifdef LOCAL
freopen("zz_in.txt", "r", stdin);
freopen("zz_op.txt", "w", stdout);
#endif
while (cin >> n) {
for (int i = 1; i <= n; i++)
cin >> a[i];
cout << lis() << endl;
}
// int e[] = {1, 2, 3, 5, 6, 7};
// cout << e[lower_bound(e, e + 6, 5) - e] << endl; //5 第一个<=5的元素
// cout << e[upper_bound(e, e + 6, 5) - e] << endl; //6 第一个>5的元素
//之前upper_bound lower_bound搞错了
// upper_bound( first, last, & val)算法返回一个非递减序列[first, last)中第一个 大于 val的地址。
// lower_bound( first, last, & val)算法返回一个非递减序列[first, last)中第一个 大于等于 值val的地址。
// upper_bound( first, last, & val, greater())算法返回一个非递增序列[first, last)中第一个 小于 val的地址。
// lower_bound( first, last, & val, greater())算法返回一个非递增序列[first, last)中第一个 小于等于 值val的地址。
// int pos = lower_bound(age.rbegin(), age.rend(), a[i]) - age.rbegin();
//rbegin rend反向迭代器(倒着查找)
#ifdef LOCAL
printf("Time used = %.2f\n", (double) clock() / CLOCKS_PER_SEC);
#endif
return 0;
}