洛谷 排列LCS P1439 (LCS)

本文介绍了一种将最长公共子序列(LCS)问题转化为最长递增子序列(LIS)问题的有效算法实现。通过使用线段树或树状数组进行优化,解决了在两个序列中寻找最大匹配子序列的问题。文章还详细解释了如何处理值不唯一的情况,并提供了一个完整的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看到黑书上写着,LCS是稀疏匹配,只需要关注能让答案更新的地方就可以了。


也就是当a[i]==b[j],dp[i+1][j+1]=dp[i][j]+1.这种情况。


所以对于每一个i,我们只需要关心,和a[i]相等的值再b种的位置j,记为pair[i]。


所以i从0开始更新,去找出pair[j]小于pair[i]的最大的dp[j],这个过程用个线段树或者树状数组优化就好了。


其实就是转换成先找到a在b种对应位置,然后根据位置的值来求lis的一个问题了。


如果值不唯一的话,就将一个值对应的所有坐标逆序排布。

比如

a: 1 3 2

b: 3 2 2 1 3

就把a对应为 (4) (5 1) (2 3)

逆序是为了保证相同的值没有重复利用,一个a[i]只能匹配一个。



代码:

#include <bits/stdc++.h>
#define lson o<<1
#define rson o<<1|1
#define MID int mid=(l+r)>>1;
using namespace std;
const int maxn=1e5+5;
int bit[maxn];
int book[maxn];
int pos[maxn];
int a[maxn];
int n;

int val[maxn<<2];

void update(int o, int l, int r, int x, int y)
{
    if(l==r)
    {
        val[o]=max(val[o], y);
        return;
    }

    MID;
    if(x>mid)update(rson, mid+1, r, x, y);
    else update(lson, l, mid, x, y);

    val[o]=max(val[lson], val[rson]);

    return;
}

int query(int o, int l, int r, int x, int y)
{
    if(x<=l && r<=y)
    {
        return val[o];
    }

    MID

    int res=0;
    if(x<=mid)res=query(lson, l, mid, x, y);
    if(y>mid)res=max(res, query(rson, mid+1, r, x, y));

    return res;
}



int main()
{
    int  i, j;
    cin>>n;
    for(i=1; i<=n; i++)
    {
        scanf("%d", &a[i]);
        book[a[i]]=i;
    }
    for(i=1; i<=n; i++)
    {
        scanf("%d", &a[i]);
        pos[book[a[i]]]=i;
    }
    int ans=1;
    int ma=0;
    update(1, 1, n, pos[1], 1);
    for(i=2; i<=n; i++)
    {
        if(pos[i]-1>=1)ma=query(1, 1, n, 1, pos[i]-1);
        else ma=0;
        update(1, 1, n, pos[i], ma+1);
        ans=max(ans, ma+1);
    }
    printf("%d\n", ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值