求证明正确性
查看原帖
求证明正确性
826079
Autumn_Rain楼主2024/10/13 14:02

比赛结束约3/4h前,我打了一份45pts的暴力。

但是我有个奇怪的问题,此程序的所有 f[i][2]f[i][2]f[i][3]f[i][3],只要改动其中一个输出结果就会出错。赛时我认为这个转移是很荒谬的,因为我感觉46行应该加一句f[i][3]=a[i]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;
}


2024/10/13 14:02
加载中...