最长公共上升子序列 | LCIS、O(n^2)

想总结一下此类问题,总是鸽!

今天决定不鸽!

最长公共上升子序列也就是LCS与LIS的结合体


此时如何做到O(n^2)呢?

考虑f(i,j)表示a数组的前i个与b数组的前j个构成的并且以a[i]与b[j]结尾的最长公共上升子序列

此时用网格图考虑一下:

  2 4 3 6 5
2 1

0

0 0 0
5 1 0 0 0 2
6 1 0 0 1 2
3 1 0 2 1 2

因为以a[i],b[j]结尾,所以a[i] == b[j],所以只需要考虑a[i]即可。

对b建立一个一维数组dp——这个地方其实可以二维,但是没必要

如果此时b[j]<a[i],那么此时dp[j]就可以链接a[i],但此时需要找到一个b[j]与a[i]相同进行转移

如果此时b[j] == a[i],那么可以进行转移,转移时就直接转移到之前的<a[i]的最大的dp值即可

证明一下正确性:

首先dp数组的状态一定是a的前i-1个与b更新形成的

所以当a[i] == b[j]时,记录j之前的b[k] < a[i] 的最大值,那么就等于从i-1,k-1之前选了一个最大的并且满足小于情况的最大值

并且这样更新不影响dp状态的后续更新(无后效性)

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define rep(i,n) for(int i=1;i<=(n);i++)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pp;
const ll INF=1e17;
const int Maxn=2e7+10;
const int maxn =2e5+10;
const int mod=998244353;
const int Mod = 1e9+7;
const double eps=1e-3;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
ll dp[305],a[305],b[305];
int main(){
    read(n);
    for(int i=1;i<=n;i++) read(a[i]);
    for(int i=1;i<=n;i++) read(b[i]);
    ll ans = 0;
    for(int i=1;i<=n;i++){
        int pos = 0;///指向最大位置
        for(int k=1;k<=n;k++){
            if(b[k]<a[i]&&dp[k]+1>dp[pos]) pos = k;
            if(b[k]==a[i]) dp[k] = max(dp[k],dp[pos]+1);
        }
    }
    for(int i=1;i<=n;i++) ans = max(ans,dp[i]);
    printf("%lld\n",ans);
    return 0;
}
/**
0 1 1 1 1 1
0 1 0 1 1 1
0 1 0 1 1 1
**/
 
 
 
/**************************************************************
    Problem: 15170
    User: ldu201804
    Language: C++
    Result: 正确
    Time:1 ms
    Memory:2032 kb
****************************************************************/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/107409925