uva-10635 Prince and Princess LCS转化为LIS

来源:互联网 发布:空间数据的编辑 编辑:程序博客网 时间:2024/04/19 07:24


题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=18



一个序列的最大长度是250*250,如果当作普通的LCS问题处理,得开二维数组dp[][],对于此题绝对是无限爆内存的。

题目的特殊之处在于:

*(关键)1.每个序列的元素各不相同。

2.元素的值是有一定范围的,这位用bool vis[]创造了条件。


1.首先,要标记出哪些元素是两个序列中都出现的,对于只在一个序列中出现的元素,不予考虑。


2.利用map建立映射,将LCM问题转化为LIS问题:

设上面的序列是b,下面的序列是a。

首先将a[i]全部映射为i,(map[a[i]  ]=i;)

之后将b[i]改为map[ b[i] ]。


之后考虑b的最长上升子序列。




/**========================================== *   This is a solution for ACM/ICPC problem * *   @source:uva-10635 Prince and Princess *   @type:  dp *   @author: wust_ysk *   @blog:  http://blog.csdn.net/yskyskyer123 *   @email: 2530094312@qq.com *===========================================*/#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<algorithm>#include<map>using namespace std;typedef long long ll;const int INF =0x3f3f3f3f;const int maxn= 250*250   ;bool visA[maxn+20],visB[maxn+20];int a[maxn+10],b[maxn+10];int n,lenA,lenB;map<int,int >mp;struct myQueue{    int rear;    int q[maxn+10];    void clear()    {        rear=1;    }    int size()    {        return rear-1;    }    int search(int x)    {        int le=1,ri=rear-1;        while(le<=ri)        {            int mid=(le+ri)>>1;            if( q[mid]<x )   le=mid+1;            else   ri=mid-1;        }        return le;    }    void insert(int x)    {        if(size()==0|| q[rear-1]<x )        {            q[rear++]=x;            return;        }        int p=search(x);        q[p]=x;    }}Q;int main(){    int T,kase=0;scanf("%d",&T);    while(T--)    {        scanf("%d%d%d",&n,&lenB,&lenA);//之前lenB和lenA 弄反了,这种错误以前也犯过。        lenA++,lenB++;        memset(visB,0,(lenB+1)*sizeof visB[0]);        memset(visA,0,(lenA+1)*sizeof visA[0]);        for(int i=1;i<=lenB;i++)        {            scanf("%d",&b[i]);            visB[b[i]]=1;        }        for(int i=1;i<=lenA;i++)        {            scanf("%d",&a[i]);            visA[a[i]]=1;        }        mp.clear();        for(int i=1;i<=lenA;i++) if(visB[ a[i] ]  )        {            mp[a[i] ]=i;        }        Q.clear();        for(int i=1;i<=lenB;i++)  if(visA[ b[i] ])        {             Q.insert(mp[b[i]]);        }        printf("Case %d: %d\n",++kase,Q.size());    }   return 0;}


之后,发现自己还是写的太搓,并不需要用vis[]+map,直接开数组即可。

lower_bound()可以直接解决问题。

0 0