【Codeforces 933A】A Twisty Movement | dp、思维

题目链接:https://codeforces.com/contest/933/problem/A

昨晚睡觉前时看到的题目,感觉是个dp,便收藏了

题目大意:

给出一个由12和组成的序列,现在你可以翻转一个区间,询问翻转一个区间后,最长的不下降子序列是多少?

题目思路:

经典区间翻转问题..

刚开始读错题目,以为不只有1和2,想了好一会

那么既然只有1 和 2

那么就可以用3种状态表示最终最长不下降子序列的的形式:

1.11 - > 1 1 1 1 1

2.01 - > 0 0 0 1 1

3.00 - > 0 0 0 0 0

其次,首先预处理一下,前缀pre 3种状态的长度 与 后缀 3种状态的长度

最后,枚举每一个右端点,然后根据枚举前缀3种长度时的转移,去维护01 11 00

对于每一个能拼接的状态,都能求一个最大值即可

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 2e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
int pre[maxn][4],suf[maxn][4];
int num[maxn];
int main(){
    read(n);
    for(int i=1;i<=n;i++) read(num[i]);
    for(int i=1;i<=n;i++){
        for(int k=0;k<3;k++) pre[i][k] = pre[i-1][k];
        if(num[i] == 1) pre[i][0] ++;///00
        else{
            pre[i][2] ++;///11
            if(pre[i-1][0]) pre[i][1] = max(pre[i][1],pre[i-1][0]+1);///01
            if(pre[i][1]) pre[i][1] = max(pre[i][1],pre[i-1][1]+1);///01
        }
    }
    for(int i=n;i>=1;i--){
        for(int k=0;k<3;k++) suf[i][k] = suf[i+1][k];
        if(num[i] == 2) suf[i][2]++;///11
        else{
            suf[i][0]++;
            if(suf[i+1][1]) suf[i][1] = max(suf[i][1],suf[i+1][1]+1);
            if(suf[i+1][2]) suf[i][1] = max(suf[i][1],suf[i+1][2]+1);
        }
    }
    ll ans = 0;
    for(int i=1;i<=n;i++){
        ll a = 0,b = 0,c = 0;
        for(int k=i;k>=1;k--){
            if(num[k] == 1){
                b++;
                ll tempc = c;
                if(a) c = max(c,a+1ll);
                if(tempc) c = max(c,tempc+1);
            }else a++;
            ///00
            ans = max(ans,pre[k-1][0]+a+max(suf[i+1][0],max(suf[i+1][1],suf[i+1][2])));
            ///01
            ans = max(ans,pre[k-1][0]+c+suf[i+1][2]);
            ///11
            ans = max(ans,max(pre[k-1][0],max(pre[k-1][1],pre[k-1][2]))+b+suf[i+1][2]);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

/***
****/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/111340668