P2102 LCIS

P2102\(\mathbf{} \begin{Bmatrix} \frac{{\Large SLOJ-P2102} }{{\color{Red}\Large Solution} }\mathbf{} {No.17} \end{Bmatrix}\times{}\) NeeDna

题意:求 \(a,b\) 两个串的最长公共上升子序列长度

(为CF10D简化版)

先思考朴素暴力,设 \(f_{i,j}\) 为在 \(a\) 中前 \(i\) 位,末尾为 \(b[ j ]\) 的答案。那么考虑转移,可以从 \(f_{i-1,j}\) 中直接转移,然后如果 \(a[i]=b[k],k \in[0,j-1]\) 那么可以转移 \(f_{i-1,k}+1\) 。这暴力就是 \(O(n^3)\) 的了。考虑优化,发现瓶颈在枚举 \(k\) 上,接着发现 \(f_{i-1,k}+1\)\(j\) 增长的时候是单调不减的,所以用一个数保存一下即可,更新决策点当且仅当 \(a[i]>b[j]\),此时才可能保留单调性。

ac code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,M=5e3+10;
int n,a[N],b[N],f[M][M],ans;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1;i<=n;i++){
		int maxv=1;
		for(int j=1;j<=n;j++){
			f[i][j]=f[i-1][j];
			if(a[i]==b[j]) f[i][j]=max(f[i][j],maxv);
			if(b[j]<a[i]) maxv=max(maxv,f[i-1][j]+1);
		}
	}for(int i=1;i<=n;i++) ans=max(ans,f[n][i]);
	cout<<ans;
	return 0;
}
posted @ 2025-05-30 21:05  NeeDna  阅读(12)  评论(0)    收藏  举报