Codeforces Round #462 (Div. 2), problem: (C) A Twisty Movement

本文探讨了给定长度为n的数字串(只包含1和2),通过翻转某段区间来最大化非递减子序列长度的问题。提出两种解决方法:一种基于前缀和与枚举,另一种采用DP动态规划。详细介绍了每种方法的实现思路及代码。
题目意思: 给长度为n(n<=2000)的数字串,数字只能为1或者2,可以将其中一段区间[l,r]翻转,求翻转后的最长非递减子序列长度。
第一种:先预处理1的前缀和,以及2的后缀和,每次枚举翻转区间,则答案为左区间的1的前缀和
+枚举区间内最长非递增子序列的长度+右区间2的后缀和数目。
先固定左端点l,然后枚举右端点,碰到1要统计,碰到2要更新值,假如使用此处的2,
则之前区间内的1无法继续使用。复杂度为n^2


#include<bits/stdc++.h>
using namespace std;
#define ll long long
int pre1[2010],suf2[2010];
int a[2010];
int main()
{
    int n;
    cin>>n;
    pre1[0]=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        pre1[i]=pre1[i-1];
        if(a[i]==1)
            pre1[i]++;
    }
    suf2[n+1]=0;
    for(int i=n;i>=1;i--)
    {
        suf2[i]=suf2[i+1];
        if(a[i]==2)
            suf2[i]++;
    }
    int ans=0;
   /* for(int i=1;i<=n;i++)
    {
        ans=max(ans,pre1[i]+suf2[i]);
    }*/
   for(int l=1;l<=n;l++)
    {
        int t1=pre1[l-1];
        int tt1=0,tt2=0;
        for(int r=l;r<=n;r++)
        {
            int t2=suf2[r+1];
            if(a[r]==1)
                tt1++;//l-r的最优值
            else
                {
                    tt2++;
                    tt1=max(tt1,tt2);//如果2出现,要先更新最优值,就是2的数目
                }
        ans=max(ans,t1+t2+tt1);
        }
    }
    cout<<ans<<endl;
    return 0;
}
第二中方法,采用dp思想,每一个最优答案可视为1串+...+2串+..+1串+..+2串..的组合,则

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int pre1[2010],suf2[2010];
int a[2010];
int dp[2010][2010][3];
int main()
{
    int t1=0,t2=0,t3=0,t4=0;
    int n,x;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        if(x==1)
        {
            t1++;
            t3=max(t3,t2)+1;
        }
        else
        {
            t2=max(t2,t1)+1;
            t4=max(t3,t4)+1;
        }
    }
    cout<<max(t3,t4)<<endl;
    return 0;
}
时间复杂度为n

做这种题还是要多动笔,分类找规律,列方程,优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值