Codeforces Round #462 (Div. 1)A. A Twisty Movement()

版权声明:《学习技巧》每次使用单边大脑的时间不要太久,连续使用左边大脑30分钟就如同连续使用左臂30分钟一样,周期性的交换让大脑两侧能够轮流休息,左脑活动包括了循序渐进的工作,解决逻辑问题与分析,而右脑活动包括了隐喻,创造性思考,模式匹配和可视化。 https://blog.csdn.net/intmainhhh/article/details/82933309

题目传送门
题目大意:
问题描述
给你一个仅包含数字1,2且长度为n的序列a[1…n].
现在,你可以选择一个区间l,r(1<=l<=r<=n),然后翻转a[l…r]里面的数字.
*比如a={4,5,6},那么翻转a[2…3]之后,a={4,6,5}.
*你可以选择让l==r,那么这个时候a数组没有发生变化.
*设1<=x1< x2< …< xk<=n,且a[x1]<=a[x2]<=…<=a[xk],那么a[x1],a[x2],…,a[xk]就称为一个不下降子序列,k就是这个不下降子序列的长度.
请你选取合适的l,r使得产生的新的序列,它的最长不下降子序列的值最大.
你的任务是输出这个最大值.
输入格式
第一行一个正整数n(1<=n<=2000),表示序列的长度.
第二行有n个整数,第i个数字代表ai(1<=ai<=2).
输出格式
输出只有一个整数,对于给定的序列,请输出题中所要求的最大值.
样例
样例输入
4
1 2 1 2
样例输出
4
样例输入2
10
1 1 2 2 2 1 1 2 2 1
样例输出2
9
样例解释
对于第一个样例,翻转[2,3]这个区间,数组会变成[1,1,2,2].此时最长不下降子序列的长度为4,尝试其他[l,r]的赋值,发现最长不下降子序列的值都不会大于4.
提示
注意只会出现1,2这两个数字.
题解:求出1的前缀和,2的后缀和,以及区间[i,j]的最长不递增子序列。
dp[i][j][0]表示区间i-j以1结尾的最长不递增子序列;
dp[i][j][1]表示区间i-j以2结尾的最长不递增子序列,显然是区间i-j2的个数;
所以转移方程为:
dp[i][j][1] = dp[i][j-1][1] + (a[j]==2);
dp[i][j][0] = max(dp[i][j-1][0], dp[i][j-1][1]) + (a[j]==1);(1<=i<=n,i<=j<=n)
代码如下:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=2000+10;
int arr[maxn];
int q1[maxn],h2[maxn];
int dp[maxn][maxn][2];
int main() {
    int n, t;
    cin>>n;
    for(int i=1; i<=n; i++)  {//
        cin>>arr[i];
        q1[i]+=q1[i-1]+(arr[i]==1);
    }
    for(int i=n; i>=1; i--)  {
        h2[i]=h2[i+1]+(arr[i]==2);
    }
    int ans=-1000000;
    for(int i=1;i<=n;i++) {
        for(int j=i;j<=n;j++) {
            //cout<<"------"<<endl;
            dp[i][j][1] = dp[i][j-1][1]+(arr[j]==2);
            dp[i][j][0] = max(dp[i][j-1][0], dp[i][j-1][1])+(arr[j]==1);
            ans=max(ans,dp[i][j][1]+q1[i-1]+h2[j+1]);
            ans=max(ans,dp[i][j][0]+q1[i-1]+h2[j+1]);
        }
    }
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/intmainhhh/article/details/82933309