LCIS

题意:

求两个序列的LCIS,最长公共上升子序列。

题解:

结合一下LCS和LIS即可。 f [ i ] [ j ] f[i][j] f[i][j]表示 a [ 1 ⋯ i ] a[1\cdots i] a[1i] b [ 1 ⋯ j ] b[1\cdots j] b[1j]构成的LCIS长度。当 a [ i ] = = b [ j ] a[i]==b[j] a[i]==b[j]时,
f [ i ] [ j ] = max ⁡ 0 ≤ k < j , b [ j ] < a [ i ] f [ i − 1 ] [ k ] + 1 f[i][j]=\max_{0\leq k<j,b[j]<a[i]}f[i-1][k]+1 f[i][j]=0k<j,b[j]<a[i]maxf[i1][k]+1
显然可以用 O ( n 3 ) O(n^3) O(n3)解决,但是可以优化一下。在内层循环 b [ j ] b[j] b[j]时, a [ i ] a[i] a[i]是固定的,且 b [ 1 ⋯ j − 1 ] b[1\cdots j-1] b[1j1]是固定的,每次实际上只是让 b [ j ] b[j] b[j]加入决策集合。对于决策集合只增不减的情景,可以用一个变量维护决策集合当前的信息,避免重复扫描,把转移降低一个复杂度。对于每个 a [ i ] a[i] a[i],先初始化 v a l = 0 val=0 val=0,代表当前最长的LCIS,当 b [ j ] < a [ i ] b[j]<a[i] b[j]<a[i]时, f [ i ] [ j ] = f [ i − 1 ] [ j ] , v a l = m a x ( f [ i ] [ j ] , v a l ) f[i][j]=f[i-1][j],val=max(f[i][j],val) f[i][j]=f[i1][j],val=max(f[i][j],val);当 b [ j ] = = a [ i ] b[j]==a[i] b[j]==a[i]时, f [ i ] [ j ] = v a l + 1 f[i][j]=val+1 f[i][j]=val+1。由 b [ j ] = = a [ i ] b[j]==a[i] b[j]==a[i]维护LCS,由 b [ j ] < a [ i ] b[j]<a[i] b[j]<a[i]维护LIS。

AC代码:

#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <iomanip>
#include <cstdlib>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define lep(i,a,b) for(int i=(a);i>=(b);i--) 
#define pb push_back 
#define fir first
#define sec second
#define All(x) x.begin(),x.end() 
#define ms(a,b) memset(a,b,sizeof(a)) 
#define INF 0x3f3f3f3f
#define multi int T;scanf("%d",&T);while(T--) 
using namespace std;
typedef long long ll;
typedef double db;
const int N=3e3+5;
const int mod=10007;
const db pi=acos(-1.0);
int a[N],b[N],n,dp[N][N];
string s;
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("D:\\work\\data.in","r",stdin);
    #endif
    int n;
    scanf("%d",&n);
    rep(i,1,n) scanf("%d",&a[i]);
    rep(i,1,n) scanf("%d",&b[i]);
    rep(i,1,n){
        int val=0;
        rep(j,1,n){
            if(a[i]==b[j]) dp[i][j]=val+1;
            else{
                dp[i][j]=dp[i-1][j];
                if(b[j]<a[i]) val=max(val,dp[i][j]);
            }
        }
    }
    int ans=0;
    rep(i,1,n) ans=max(ans,dp[n][i]); 
    printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值