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