题目大意: 给出一个 序列,允许你进行一次区间翻转,问最长不下降子序列长度。
题解
显然最后的答案是一段1序列
+一段2序列
+一段1序列
+一段2序列
,只需要把第二段和第三段所在的区间翻转即可。
那么考虑 ,设 表示前 个数中前 段的最大值,其中 。
那么显然转移的时候可以贪心地转移,比如 ,因为这个东西是没有后效性的,所以贪心地取最大就好了。
代码:
#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]);
}