[每日一题]: 最长上升子序列 AND 最长不上升子序列
关于知识点的讲解:
例题:
最长上升子序列题目链接:
普通版本:
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1005;
int dp[maxn];
int a[maxn];
int n;
int main(void) {
scanf("%d",&n);
for(int i = 1; i <= n; i ++) {
scanf("%d",&a[i]);
}
int ans = 0;
for(int i = 1; i <= n; i ++) {
dp[i] = 1;
for(int j = 1; j < i; j ++) {
if(a[i] > a[j]) {
dp[i] = max(dp[j] + 1,dp[i]);
}
}
}
for(int i = 1; i <= n; i ++) {
ans = max(ans,dp[i]);
}
cout << ans << endl;
return 0;
}
二分优化:
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
int dp[maxn],a[maxn];
int low[maxn];
int n,cnt = 1;
int serch(int x) {
int l = 1, r = cnt;
while(l < r) {
int mid = l + r >> 1;
if(low[mid] >= x) r = mid;
else l = mid + 1;
}
return r;
}
int main(void) {
scanf("%d",&n);
for(int i = 1; i <= n; i ++) {
scanf("%d",&a[i]);
}
memset(low,0x3f,sizeof(low));
low[1] = a[1];
for(int i = 1; i <= n; i ++) {
if(a[i] > low[cnt]) low[ ++ cnt] = a[i];
else {
int pos = serch(a[i]);
low[pos] = a[i];
}
}
printf("%d\n",cnt);
return 0;
}
最长不上升子序列例题:
侃侃:
这个题是在最长上升子序列版本上的改动,如果最长上升子序列搞懂了,
这个应该不难。
普通版:
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
int dp[maxn],a[maxn];
int n;
int main(void) {
scanf("%d",&n);
for(int i = 1; i <= n; i ++) {
scanf("%d",&a[i]);
}
for(int i = 1; i <= n; i ++) {
dp[i] = 1;
for(int j = 1; j < i; j ++) {
if(a[j] >= a[i]) {
dp[i] = max(dp[i],dp[j] + 1);
}
}
}
int res = 0;
for(int i = 1; i <= n; i ++) {
res = max(res,dp[i]);
}
cout << res << endl;
return 0;
}
二分优化:
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
int dp[maxn],a[maxn];
int low[maxn];
int n,cnt = 1;
int serch(int x) {
int l = 1,r = cnt;
while(l < r) {
int mid = (l + r )>> 1;
if(low[mid] < x) r = mid;
else l = mid + 1;
}
return r;
}
int main(void) {
scanf("%d",&n);
for(int i = 1; i <= n; i ++) {
scanf("%d",&a[i]);
}
memset(low,0x3f,sizeof(low));
low[1] = a[1];
for(int i = 2; i <= n; i ++) {
if(a[i] <= low[cnt]) {
low[++ cnt] = a[i];
} else {
int pos = serch(a[i]);
low[pos] = a[i];
}
}
printf("%d\n",cnt);
return 0;
}
如果说年轻人未来是一场盛宴的话,那么我首先要有赴宴的资格。