思路:dp
很容易想到要预处理出1的前缀和pre[i]和2的后缀和suf[i]
然后枚举区间,对于每个区间如果能求出最长递减序列的长度,那么就能更新答案了
这个用dp求
状态:
dp[i][j][0]表示i--j区间以2结尾的最长递减序列长度,很明显这个序列全为2,所以也就是i--j区间2的个数
dp[i][j][1]表示i--j区间以1结尾的最长递减序列长度
状态转移:
dp[i][j][0]=dp[i][j-1][0]+(a[j]==2)
dp[i][j][1]=max(dp[i][j-1][0],dp[i][j-1][1])+(a[j]==1)
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=2e3+5; int a[N]; int pre[N]; int suf[N]; int dp[N][N][2]; int main(){ ios::sync_with_stdio(false); cin.tie(0); int n; cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++)pre[i]=pre[i-1]+(a[i]==1); for(int i=n;i>=1;i--)suf[i]=suf[i+1]+(a[i]==2); int ans=0; for(int i=1;i<=n;i++){ for(int j=i;j<=n;j++){ dp[i][j][0]=dp[i][j-1][0]+(a[j]==2); dp[i][j][1]=max(dp[i][j-1][0],dp[i][j-1][1])+(a[j]==1); ans=max(ans,pre[i-1]+suf[j+1]+dp[i][j][0]); ans=max(ans,pre[i-1]+suf[j+1]+dp[i][j][1]); } } cout<<ans<<endl; return 0; }