UVA 10635 Prince and Princess(最长上升子序列)
2015-07-17 22:43
316 查看
题意:有n*n的格子用1-n*n不同的数表示,第一个人输入p+1长度的数,第二个人输入q+1个不同的数,问他们最长公共子序列最长是多长。
分析:由于(0<=n<=250,n*n最大=250*250),用O(n^2)的算法是不能解决的,需要一种nlog(n)的算法。由于这里比较特殊,每个人输入的数都是不重复的,那么就把第一个人输入的数映射成1,2,3……,第二个人输入的数映射对应第一个人输入数的映射。这样,第一个人的映射是递增的,那么我只需要找到第二个人的映射的最长上升子序列的个数就是ans。
那么怎么求这个最长上升子序列呢?假设求1,4,6,3,5,7,最长上升子序列
dp[i]:表示长度为i,最小的那个数
①加入1,dp[1]=1;②加入4,dp[2]=4;③加入6,dp[3]=6;④加入3,dp[2]=3;⑤加入5,dp[3]=5;⑥加入7,dp[4]=7;
所以最终ans=4,这里,应为dp[]里存的数都是单调递增的,因此可以二分查找或lower_bound(加入的数)的id,更新dp[id]。
分析:由于(0<=n<=250,n*n最大=250*250),用O(n^2)的算法是不能解决的,需要一种nlog(n)的算法。由于这里比较特殊,每个人输入的数都是不重复的,那么就把第一个人输入的数映射成1,2,3……,第二个人输入的数映射对应第一个人输入数的映射。这样,第一个人的映射是递增的,那么我只需要找到第二个人的映射的最长上升子序列的个数就是ans。
那么怎么求这个最长上升子序列呢?假设求1,4,6,3,5,7,最长上升子序列
dp[i]:表示长度为i,最小的那个数
①加入1,dp[1]=1;②加入4,dp[2]=4;③加入6,dp[3]=6;④加入3,dp[2]=3;⑤加入5,dp[3]=5;⑥加入7,dp[4]=7;
所以最终ans=4,这里,应为dp[]里存的数都是单调递增的,因此可以二分查找或lower_bound(加入的数)的id,更新dp[id]。
#include <iostream> #include <stdio.h> #include <math.h> #include <algorithm> #include <queue> //http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82285#problem/E
#include <stack> #include <vector> #include <string> #include <string.h> #include <map> #include <set> using namespace std; #define maxn 250*251 #define inff 1000000000 int a[maxn],b[maxn],dp[maxn]; int lower_bound(int aa[],int size,int k)//查找第一个>=k的数的id { int l,r,mid; l=0;r=size-1; while(l <= r) { mid=(l+r)/2; if(aa[mid] >= k) r = mid - 1; else l = mid + 1; } return l; } int main() { int t,k,n,num1,num2,i,m,tt=1; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&num1,&num2); num1++; num2++; memset(a,-1,sizeof a); memset(b,-1,sizeof b); for(i=1;i<=num1;i++) { scanf("%d",&m); a[m]=i;//把第一个人的数映射成1,2,3…… } k=1; for(i=1;i<=num2;i++) { scanf("%d",&m); if(a[m]!=-1) b[k++]=a[m];//第二个人输入的数,参照第一个人的映射,存下该数的映射 } for(i=0;i<maxn;i++) { dp[i]=inff; } dp[0]=-1;//令dp[0]最小 for(i=1;i<k;i++) { int j=lower_bound(dp,maxn-1,b[i]); dp[j]=b[i]; } for(i=1;i<maxn;i++) { if(dp[i]==inff) { printf("Case %d: %d\n",tt++,i-1); break; } } } return 0; }
相关文章推荐
- 【上海交大oj】畅畅的牙签袋(改)(枚举+模拟)
- 集成激光推送
- Unity使用 16bit 压缩 Texture 颜色能均匀过渡
- ColorViewPager--动态改变ViewPager的背景,给你一个漂亮的ViewPager
- 神奇的Intent
- OC基础---protocol、category和继承的区别
- 大数据架构:flume-ng+Kafka+Storm+HDFS 实时系统组合
- 关于轻松安装LNMP和LAMP的编译环境
- 用Fragment实现Tab页面切换效果初步总结
- 一个很好地List实现源码
- Hibernate(八)Session方法、事务隔离级别及懒加载
- CALayer 定制下载进度条控件
- JS DOM编程艺术——显示文献来源链接表—— JS学习笔记2015-7-17(第86天)
- org.hibernate.id.IdentifierGenerationException错误解决方法
- 一览新的 Android Gradle 构建工具:新的 DSL 结构 和 Gradle 2.5
- org.hibernate.id.IdentifierGenerationException错误解决方法
- org.hibernate.id.IdentifierGenerationException错误解决方法
- POJ-3748 位操作
- 人群密度检测论文笔记
- int A[nSize],其中隐藏着若干0,其余非0整数,写一个函数int Func(int* A, int nSize),使A把0移至后面,非0整数移至 数组前面并保持有序,返回值为原数据中第一个