思路:题目给定的数字序列只包括1和2,要求翻转区间[l,r],使得新序列的非递减(>=)子序列长度尽可能长,求最大可能长度。(只翻转1次!)
本题读入数据规模较大,需注意优化读入。
C++ 尽量使用 scanf 读入,Java 尽量使用 BufferedReader 读入。
最优情况为:先增后减再增(即11111222221111122222)
把此序列分为四部分:s1:11111,s2:22222,s3:11111,s4:22222
分别求s1长度,s1+s2长度,s1+s2+s3长度,s1+s2+s3+s4长度的最大值
初始条件下四个状态的长度均为0:
输入1:s1=s1+1;s3的长度等于(s2长度+连续1的长度),最坏情况下只有1个1,此时s3=s2+1,如果不是最坏情况,s3=s3+1。
输入2:s2的长度等于(s1长度+连续2的长度),最坏情况下只有1个2,此时s2=s1+1,如果不是最坏情况,s2=s2+1;s4的长度等于(s3长度+连续2的长度),最坏情况下只有1个2,此时s4=s3+1,如果不是最坏情况,s4=s4+1。
最后结果取s3与s4两个状态的最大值即可。
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,x;
scanf("%d",&n);
int s1=0,s2=0,s3=0,s4=0;
while(n--){
scanf("%d",&x);
if(x==1){
s1++;
s3=max(s2+1,s3+1);
}
else if(x==2){
s2=max(s1+1,s2+1);
s4=max(s3+1,s4+1);
}
}
cout<<max(s3,s4);
return 0;
}