题目大意: 给出一个 12 12 12 序列,允许你进行一次区间翻转,问最长不下降子序列长度。
显然最后的答案是一段1序列
+一段2序列
+一段1序列
+一段2序列
,只需要把第二段和第三段所在的区间翻转即可。
那么考虑 d p dp dp,设 f [ i ] [ j ] f[i][j] f[i][j] 表示前 i i i 个数中前 j j j 段的最大值,其中 j ∈ [ 1 , 4 ] j\in[1,4] j∈[1,4]。
那么显然转移的时候可以贪心地转移,比如 f [ i ] [ 2 ] = max ( f [ i − 1 ] [ 2 ] + [ i = = 2 ] , f [ i ] [ 1 ] ) f[i][2]=\max(f[i-1][2]+[i==2],f[i][1]) f[i][2]=max(f[i−1][2]+[i==2],f[i][1]),因为这个东西是没有后效性的,所以贪心地取最大就好了。
代码:
#include <cstdio>
#include <cstring>
int n,f[5];//第一维可以滚掉,所以没必要用
inline int max(int x,int y){return x>y?x:y;}
int main()
{
scanf("%d",&n);
for(int i=1,x;i<=n;i++)
{
scanf("%d",&x);
f[1]+=(x==1);
f[2]=max(f[1],f[2]+(x==2));
f[3]=max(f[2],f[3]+(x==1));
f[4]=max(f[3],f[4]+(x==2));
}
printf("%d",f[4]);
}