codeforces 1272D Remove One Element (dp)
题目链接:https://codeforces.com/problemset/problem/1272/D
DP
设 \(dp[i][0/1]\) 表示上升子序列的最后一个位置是 i ,之前是/否删除过的最大长度
当前元素不删,考虑前一个元素删不删, 则状态转移方程为:
\[if(a[i] > a[i-1]) \quad dp[i][0] = max(dp[i][0],dp[i-1][0] + 1);
\]
\[if(a[i] > a[i-2]) \quad dp[i][0] = max(dp[i][0],dp[i-2][1] + 1);
\]
\[if(a[i] > a[i-1]) \quad dp[i][1] = max(dp[i][1],dp[i-1][1] + 1);
\]
最后扫描一遍,取最大值即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 200010;
int n;
int a[maxn],dp[maxn][2]; // 最长序列到第 i 个元素,之前是否删除过 0/1 是否
ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
int main(){
n = read();
for(int i=1;i<=n;++i) a[i] = read();
for(int i=1;i<=n;++i) dp[i][0] = dp[i][1] = 1;
for(int i=2;i<=n;++i){ // 考虑前一个元素删不删,当前元素不删
if(a[i] > a[i-1]) dp[i][0] = max(dp[i][0],dp[i-1][0] + 1);
if(a[i] > a[i-2]) dp[i][0] = max(dp[i][0],dp[i-2][1] + 1);
if(a[i] > a[i-1]) dp[i][1] = max(dp[i][1],dp[i-1][1] + 1);
}
int ans = 0;
for(int i=1;i<=n;++i){
ans = max(ans,max(dp[i][0],dp[i][1]));
}
printf("%d\n",ans);
return 0;
}