UVA10635 Prince and Princess(LIS变形题) --- 贪心

题意:有2个长度分别为p+1和q+1的序列,每个序列各个元素互不相同,都是1-n^2间的整数,

两个序列第一个元素为1,求两个序列的最大公共子序列长度?

2<=n<=250,1<=q,p<=n^2

题解: 本质上就是求2个数组AB的最长公共子序列,也就是LIS问题,但是朴素的LIS算法时间复杂度是O(n^2),对此题来说超时。根据蓝书上的讲解,正确方法是将A序列 的元素编号,比如A={1,7,5,4,8,3,9}则A数组改变为{1,2,3,4,5,6,7},

B={1,4,3,5,6,2,8,9},B数组变为={1,4,6,3,0,0,5,7},0表示没有在A中出现过,因为0不影响结果,所以把0去除后B={1,4,6,3,5,7},

相当于就是求该数组的最长子序列长度,最长子序列LIS算法的优化版本时间复杂度为O(nlogn),可以解决此题。

(LIS优化算法具体原理参考https://www.cnblogs.com/Bravewtz/p/10624796.html

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 90000
using namespace std;
int n,p,q;
int a[MAXN],b[MAXN];
int number[MAXN];
int temp[MAXN];


int main() {
    int Case = 1;
    int T;
    scanf("%d",&T);
    while(T--) {
        memset(number,0,sizeof(number));
        memset(temp,0,sizeof(temp));
        scanf("%d%d%d",&n,&p,&q);
        for(int i = 0;i < p+1;i++) {
            scanf("%d",&a[i]);
            number[a[i]] = i+1;
        }
        int j = 0;
        for(j = 0;j < q+1;j++) {
            scanf("%d",&b[j]);
            b[j] = number[b[j]];
        }
       int cnt = j;
       memcpy(a,b,sizeof(b));
       int l = 0;
       int r = 0;
       // erase 0 in array b
       while(l < cnt) {
            if(a[l])
                b[r++] = a[l];
            l++;
        }
        int res = 0;
        for(int i = 0;i < r;i++) {
            if(res == 0 || b[i] > temp[res-1]) {
                temp[res++] = b[i];
            } else {
                int replace = lower_bound(temp,temp+res,b[i]) - temp;
                temp[replace] = b[i];
            }
        }
        printf("Case %d: %d\n",Case++,res);

    }

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值