UVA 10635 Prince and Princess(最长公共子序列转为最长上升子序列)

题目链接:
UVA 10635 Prince and Princess
题意:
n,p,q 表示接下来两行会给 p+1 q+1 个数。每个数都不超过 nn ,且每行的数字各不相同,所以 pq 也满足: 1p,q<n 。求两个序列最长的上升的数字相同的公共子序列的长度。
数据范围: 2n250
分析:
最长公共子序列问题。
主要分析每行的数字各不相同。所以我们可以对第一行的每个数字编一个对应的编号,用 id[t] 表示第一行的数字 t 出现的位置,如果数字t没有出现,那么就 id[t]=1 。接下来对于第二行出现的数字 r ,我们其实需要知道的是它在第一行中出现的位置id[r],所以我们令 data[i]=id[r] ,最后我们只需要知道 data[i] 的最长上升子序列就得到了原来两个数组的最大公共子序列。
例如,两个数字序列分别是;
p=61,7,5,4,8,3,9
q=71,4,3,5,6,2,8,9
我们对于第一行数可以得到 id[] 数组如下:
id[1]=1,id[7]=2,id[5]=3,id[4]=4
id[8]=5,id[3]=6,id[9]=7 ,对于其余所有没出现的数字的 id[] 通通为 1
对于第二行数我们可以得到 data 数组:
data[1]=id[1]=1
data[2]=id[4]=4
data[3]=id[3]=6
data[4]=id[5]=3
data[5]=id[6]=1
data[6]=id[2]=1
data[7]=id[8]=5
data[8]=id[9]=7
我们求 data 数组的最长上升子序列可到:
1457
对应原来的两行数字是:
1489
长度是 4
时间复杂度是:O(nlog(n)),其中 n <script type="math/tex" id="MathJax-Element-111">n</script>是第二个数字序列的长度。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N = 300;
const int MAX_M = 100010;

int T, n, p, q, cases = 0;
int id[MAX_M], data[MAX_M], arr[MAX_M];

int main()
{
    scanf("%d", &T);
    while(T--) {
        memset(id, -1, sizeof(id));
        scanf("%d%d%d", &n, &p, &q);
        for(int i = 1; i <= p + 1; ++i) {
            int t;
            scanf("%d", &t);
            id[t] = i;
        }
        for(int i = 1; i <= q + 1; ++i) {
            int t; 
            scanf("%d", &t);
            data[i] = id[t];
        }
        int len = 0;
        for(int i = 1; i <= q + 1; ++i) {
            if(data[i] == -1) continue;
            int pos = lower_bound(arr, arr + len, data[i]) - arr;
            len = max(len, pos + 1);
            arr[pos] = data[i];
        }
        printf("Case %d: %d\n", ++cases, len);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值