UVA 10635 - Prince and Princess ( LCS 转换为LIS )

来源:互联网 发布:计算机编程中常见的 编辑:程序博客网 时间:2024/04/27 03:11

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1576

题        意:给你两个数组,找出最长公共子序列。

思        路:由于数组太大,所以不可以用常规方法。因此有个巧妙的转换,把A中的元素重新按1~p+1编号,

                   同时B也相同的映射编号,由于A为递增序列,所以LCS就是B中最长递增子序列,即LIS.这样就

                   转换成求B的LIS问题,可以在O(nlogn)的时间内解决。

代码如下:

#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>#include <climits>using namespace std;#define maxn 62505int s[maxn], g[maxn], d[maxn], vis[maxn];int main(){    int T;    scanf ( "%d", &T );    int cas=1;    while( T-- )    {        int p, q, n, x;        memset( vis, 0, sizeof(vis) );        scanf ( "%d %d %d", &n, &p, &q );        for( int i = 1; i <= p+1; i ++ )        {            scanf ( "%d", &x );            vis[x] = i;        }        int j = 0;        for( int i = 1; i <= q+1; i ++ )        {            scanf ( "%d", &x );            if( vis[x] ) s[j++] = vis[x];        }        for( int i = 1; i <= j; i ++ )            g[i] = INT_MAX;        for( int i = 0; i < j; i ++ )        {            * (lower_bound( g+1, g+j+1, s[i] ))= s[i];        }        printf("Case %d: %d\n",cas++,lower_bound( g+1, g+j+1, INT_MAX ) - g - 1 );    }    return 0;}

               也可以用另一种方法求LIS;

代码如下:

#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>#include <climits>using namespace std;#define maxn 62505int s[maxn], g[maxn], d[maxn], vis[maxn];int main(){    int T;    scanf ( "%d", &T );    int cas=1;    while( T-- )    {        int p, q, n, x;        memset( vis, 0, sizeof(vis) );        scanf ( "%d %d %d", &n, &p, &q );        for( int i = 1; i <= p+1; i ++ )        {            scanf ( "%d", &x );            vis[x] = i;        }        int j = 0;        for( int i = 1; i <= q+1; i ++ )        {            scanf ( "%d", &x );            if( vis[x] ) s[j++] = vis[x];        }        int ans = 0;        for( int i = 1; i <= j; i ++ )            g[i] = INT_MAX;        for( int i = 0; i < j; i ++ )        {            int k = lower_bound( g, g+j+1, s[i] ) - g;            d[i] = k;            g[k] = s[i];            ans = max( ans, d[i] );        }        printf("Case %d: %d\n",cas++,ans);    }    return 0;}

0 0