【模版】数组最大不连续递增子序列
核心思想
如果a[i]
比它前面的数大且子列长度小于前面小数维护的子列长度+1
,则更新当前子列长度 (dp
核心思想).
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#define MaxSize 100010 //注意依题更改数组大小
using namespace std;
int a[MaxSize]; //存放原始数据
int dp[MaxSize]; //存放当前最大不连续递增子列长度
int MCAO(int a[], int n){ //MaxChildArrayOrder
for (int i = 0; i < n; i++) dp[i] = 1; //初始化子列长度都为1
for (int i = 1; i < n; i++)
for (int j = 0; j < i ; j++)
if (a[i] > a[j] && dp[j]+1 > dp[i])
//如果a[i]比它前面的数大且子列长度小于前面小数维护的子列长度+1
//则更新当前子列长度 (dp核心思想)
dp[i] = dp[j] + 1;
int Max = dp[0];
for (int i = 1; i < n; i++) Max = max(Max, dp[i]); //取出最大不连续递增子列长度
return Max;
}
int main() {
int n;
scanf("%d", &n); //元素个数
for (int i = 0; i < n; i++) scanf("%d", &a[i]); //获取元素
printf("%d\n", MCAO(a, n)); //求最大不连续递增子列长度
return 0;
}
测试样例
输入:
9
3 1 4 1 5 9 2 6 5
输出:
4
路径输出
#include <iostream>
#include <cstdio>
#include <algorithm> // max
#include <vector>
#define MaxSize 100010 // 注意依题更改数组大小
using namespace std;
int a[MaxSize]; // 存放原始数据
int dp[MaxSize]; // 存放当前最大不连续递增子列长度
int p[MaxSize]; // 存放前驱, 用于输出路径
int n; // 元素个数
// MaxChildArrayOrder, 返回最大不连续递增子列长度在dp[]中的下标
int MCAO(){
for (int i = 0; i < n; i++){
dp[i] = 1; // 当前最大不连续递增子列长度初始化为1
p[i] = i; // 初始化前驱为自身
}
for (int i = 1; i < n; i++){
for (int j = 0; j < i ; j++){
if (a[i] > a[j] && dp[j]+1 > dp[i]){
// 如果a[i]比它前面的数大且子列长度小于前面小数维护的子列长度+1
// 则更新当前子列长度 (dp核心思想)
dp[i] = dp[j] + 1;
// 存放前驱
p[i] = j;
}
}
}
// 最大不连续递增子列长度在dp[]中的下标
int Max = dp[0], mxidx = 0;
for (int i = 1; i < n; i++){
if (dp[i] > Max){
Max = dp[i];
mxidx = i;
}
}
return mxidx;
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
int MaxLength = dp[MCAO()]; // 最大不连续递增子列长度
printf("%d\n", MaxLength);
vector<int> v; // 输出路径
v.push_back(a[MCAO()]); // 路径最后一个元素
int pre = p[MCAO()]; // 前驱元素
for (int i = 1; i < MaxLength; i++){
v.push_back(a[pre]);
pre = p[pre];
}
// 逆向输出
printf("%d", v[v.size()-1]);
for (int i = int(v.size()-2); i >= 0; i--) printf(" %d", v[i]);
return 0;
}