The sol to pairing

The sol to pairing

https://www.luogu.com.cn/problem/P11187

思路

把答案序列中相邻而相等的两个数,我们称之为“块”。那么可以发现,对于以某块为结尾的一个答案序列,其一定是由一个 结尾不为该块的序列 转移而来。因而,本题具有最优子结构性质,可以使用动态规划求解。

\(1.\) 对于偶数位,考虑到第偶数个数需要从上一个相同的数转移而来,预处理一个数组,存储上一个与之相同的数的下标。

\(2.\) 对于奇数位,维护最大、次大值且要保证最大次大值不相等,来应对相邻块之间值相等的情况。

Code

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int n;
int a[N];
int f[N][3];
int pre[N];
int num[N];
int fi=0,se=0;

int main(){
    freopen("pairing.in","r",stdin);
    freopen("pairing.out","w",stdout);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(!num[a[i]]) num[a[i]]=i;
        else{
            pre[i]=num[a[i]];
            num[a[i]]=i;
        }
    }
    // for(int i=1;i<=n;i++) cout<<pre[i]<<" ";cout<<endl;
    // memset(f[1],-0x3f,sizeof f[1]);
    f[0][1]=-0x3f3f3f3f;
    for(int i=1;i<=n;i++){
        int j=pre[i];
        //cout<<pre[i]<<endl;
        f[i][0]=max(f[i-1][0],f[i-1][2]);
        f[i][2]=max(f[i][2],f[j][1]+1);
        if(a[i]==a[fi]) f[i][1]=max(f[i][1],f[se][2]+1);
        else f[i][1]=max(f[i][1],f[fi][2]+1);
        if(f[i][2]>=f[fi][2]){
            if(a[i]!=a[fi]) se=fi;
            fi=i;
        }
        else if(f[i][2]>=f[se][2]) se=i;
    }
    cout<<max(f[n][0],f[n][2])<<endl;
    return 0;
}

Happy day!!!--这题调了好久,嘤嘤嘤。
https://www.luogu.com.cn/record/188550038

posted @ 2024-11-13 19:57  Qian·JXのjoker  阅读(4)  评论(0编辑  收藏  举报