其他分享
首页 > 其他分享> > ACM模板笔记:最长不下降/上升子序列,最长公共子序列(DP)

ACM模板笔记:最长不下降/上升子序列,最长公共子序列(DP)

作者:互联网

这只是我个人的备忘录,没有详细的注解,想了解原理的请去找其他的贴子 ,如果你能看得懂就将就看:P

淦宁佬,能拿到蓝桥杯省二就算成功:(,ACM拿锤子奖,我这说唱专业的说唱学生百分百白给,是这样的

求最长不上升子序列
-1s算法

	int maxr = 0;
	for (int i = counter; i >= 1; i--) {
		dp[i] = 1;
		for (int j = i + 1; j <= counter; j++) {
			if (datas[j] <= datas[i]) {
				dp[i] = max(dp[i], dp[j] + 1);
			}
		}
		maxr = max(maxr, dp[i]);
	}
	cout << maxr << endl;

在这里插入图片描述
nlogn算法(在做了,在做了)

求最长不下降子序列
-1s算法

	int ans2 = 0;
	for (int i = 1; i <= counter; i++) {
		dp2[i] = 1;
		for (int j = 1; j < i; j++) {
			if (datas[j] < datas[i])
				dp2[i] = max(dp2[i], dp2[j] + 1);
		}
		ans2 = max(ans2, dp2[i]);
	}
	cout << ans2;

在这里插入图片描述

nlogn算法(在做了,在做了)

最长公共子序列

-1s做法

	for(int i=1;i<=n;i++)
	{
		dp[i]=1;//初始化 
		for(int j=1;j<i;j++)//枚举i之前的每一个j 
		if(data[j]<data[i] && dp[i]<dp[j]+1)
		//用if判断是否可以拼凑成上升子序列,
		//并且判断当前状态是否优于之前枚举
		//过的所有状态,如果是,则↓ 
		dp[i]=dp[j]+1;//更新最优状态 
		
	}

nlogn做法

	for(int i=1;i<=n;i++){
		int l=0,r=len,mid;
		if(map[b[i]]>f[len])f[++len]=map[b[i]];
		else {
			while(l<r){	
			    mid=(l+r)/2;
			    if(f[mid]>map[b[i]])r=mid;
				else l=mid+1; 
			}
			f[l]=min(map[b[i]],f[l]);
     	}
    }

这玩意也可以离散化(来自洛谷)
在这里插入图片描述

int n,a[100005];
int ans,ma,c[100005],b[100005],r[100005];
//二分
int fen(int x){
	int le=0,ri=ma,mid;
	while(le<ri){
		mid=(le+ri)/2+1;
		if(r[mid]>=x) ri=mid-1;
		else le=mid;
	}
	return le;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i],c[a[i]]=i;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		b[i]=c[x];//这里做离散化
	}
	//然后就用普通的n^2
	int maxr = 0;
	for (int i = n; i >= 1; i--) {
		r[i] = 1;
		for (int j = i + 1; j <= n; j++) {
			if (b[j] <= b[i]) {
				r[i] = max(r[i], r[j] + 1);
			}
		}
		maxr = max(maxr, r[i]);
	}
	cout << maxr << endl;
	cout<<ans;
	return 0;
}

标签:le,int,max,mid,ACM,maxr,序列,最长,dp
来源: https://blog.csdn.net/qq_46207392/article/details/114751940