Nowcoder 牛牛的数列
摘要
Title: Nowcoder 牛牛的数列
Tag: dp、前缀、后缀
Memory Limit: 64 MB
Time Limit: 1000 ms
Powered by:NEFU AB-IN
Nowcoder 牛牛的数列
-
题意
牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。
-
思路
需要预处理出来两个数组
pre[i]
表示 以i为结束最长的上升子序列的长度post[i]
表示 以i为开始最长的上升子序列的长度
这样最大值的选取就显而易见了
- 不改
a[i]
, 那么就两个数值取最大值max(pre[i], post[i])
- 改
a[i]
- 单方面
max(pre[i - 1] + 1, post[i + 1] + 1)
就是说取一个的,然后把a[i]
这个数变成满足前一个的 - 双方面 如果
a[i + 1] - a[i - 1] >= 2
说明两个数之间能放一个数,那么就是pre[i - 1] + post[i + 1] + 1
- 单方面
这些数求个最大值即可
-
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using namespace std;
signed main(){
int n;
cin >> n;
vector<int> a(n);
for(int i = 0; i < n; ++ i) cin >> a[i];
vector<int> pre(n), post(n);
int last = 0;
// 以i为结束最长的上升子序列的长度
for(int i = 0; i < n; ++ i){
if(!i || a[i] > a[i - 1]){
pre[i] = ++ last;
}
else{
pre[i] = 1;
last = 1;
}
}
last = 0;
// 以i为开始最长的上升子序列的长度
for(int i = n - 1; i >= 0; -- i){
if(i == n - 1 || a[i + 1] > a[i]){
post[i] = ++ last;
}
else{
post[i] = 1;
last = 1;
}
}
int ans = 1;
for(int i = 0; i < n; ++ i){
ans = max({ans, pre[i], post[i]});
if(i) ans = max(ans, pre[i - 1] + 1);
if(i != n - 1) ans = max(ans, post[i + 1] + 1);
if(i && i != n - 1 && a[i + 1] - a[i - 1] >= 2) {
ans = max(ans, pre[i - 1] + post[i + 1] + 1);
}
}
cout << ans;
return 0;
}