比赛结束约3/4h前,我打了一份45pts的暴力。
但是我有个奇怪的问题,此程序的所有 f[i][2] 和 f[i][3],只要改动其中一个输出结果就会出错。赛时我认为这个转移是很荒谬的,因为我感觉46行应该加一句f[i][3]=a[i],所以是为什么会这样呢?
赛时过第三个样例的时候我整个人都是懵的。
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=5e5+10;
#define ll long long
int a[N],t[N],f[N][5],ans;
//f[i][0]:以i结尾,i未被选的最长配对子序列
//f[i][1]:以i结尾,i被选的最长配对子序列
//可能有两种情况,分类讨论
//f[i][2]:以i结尾,最长配对子序列的最后一个数字
//f[i][3]:以i结尾,最长配对子序列的最后一个数字
int main(){
// freopen("pairing3.in","r",stdin);
// freopen("pairing3.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
t[i]=a[i];
}
sort(t+1,t+n+1);
int cnt=unique(t+1,t+n+1)-t-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(t+1,t+cnt+1,a[i])-t;
}
for(int i=1;i<=n;i++){
if(f[i-1][0]>f[i-1][1]){
f[i][2]=f[i-1][2];
f[i][3]=f[i-1][3];
}
else if(f[i-1][0]<f[i-1][1]){
f[i][2]=a[i-1];
f[i][3]=a[i-1];
}
else{
f[i][2]=f[i-1][2];
f[i][3]=a[i-1];
}
f[i][0]=max(f[i-1][0],f[i-1][1]);
for(int j=1;j<i;j++){
if(a[i]!=a[j])continue;
if(f[j][2]==a[i]&&f[j][3]==a[i])continue;
//如果上一个配对子序列始终无法和当前配对,跳过
//可以证明正确性:因为如果硬要用当前这个数字,
//和前面提前要一个数字是等价的
f[i][1]=max(f[i][1],f[j][0]+2);
f[i][2]=a[i];
// cout<<i<<" "<<j<<"\n";
}
}
for(int i=1;i<=n;i++){
ans=max(ans,max(f[i][0],f[i][1]));
}
cout<<ans;
return 0;
}