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
",ans);
	
	return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/13819377.html