Hdu5748-Bellovin-最长上升子序列(LIS)

来源:互联网 发布:淘宝客好做吗 编辑:程序博客网 时间:2024/05/23 19:14

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5748

Bellovin

   
 Accepts: 428
   
 Submissions: 1685
 Time Limit: 6000/3000 MS (Java/Others)
   
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
Peter有一个序列a_1,a_2,...,a_na1,a2,...,an. 定义F(a_1,a_2,...,a_n)=(f_1,f_2,...,f_n)F(a1,a2,...,an)=(f1,f2,...,fn), 其中f_ifi是以a_iai结尾的最长上升子序列的长度.Peter想要找到另一个序列b_1,b_2,...,b_nb1,b2,...,bn使得F(a_1,a_2,...,a_n)F(a1,a2,...,an)F(b_1,b_2,...,b_n)F(b1,b2,...,bn)相同. 对于所有可行的正整数序列, Peter想要那个字典序最小的序列.序列a_1, a_2, ..., a_na1,a2,...,anb_1, b_2, ..., b_nb1,b2,...,bn字典序小, 当且仅当存在一个正整数ii (1 \le i \le n)(1in)满足对于所有的kk (1 \le k < i)(1k<i)都有a_k = b_kak=bk并且a_i < b_iai<bi.
输入描述
输入包含多组数据, 第一行包含一个整数TT表示测试数据组数. 对于每组数据:第一行包含一个整数nn (1 \le n \le 100000)(1n100000)表示序列的长度. 第二行包含nn个整数a_1,a_2,...,a_na1,a2,...,an (1 \le a_i \le 10^9)(1ai109).
输出描述
对于每组数据, 输出nn个整数b_1,b_2,...,b_nb1,b2,...,bn (1 \le b_i \le 10^9)(1bi109)表示那个字典序最小的序列.
输入样例
311055 4 3 2 131 3 5
输出样例
11 1 1 1 11 2 3


题意

Peter有一个序列a_1,a_2,...,a_na1,a2,...,an. 定义F(a_1,a_2,...,a_n)=(f_1,f_2,...,f_n)F(a1,a2,...,an)=(f1,f2,...,fn), 其中f_ifi是以a_iai结尾的最长上升子序列的长度.Peter想要找到另一个序列b_1,b_2,...,b_nb1,b2,...,bn使得F(a_1,a_2,...,a_n)F(a1,a2,...,an)F(b_1,b_2,...,b_n)F(b1,b2,...,bn)相同. 对于所有可行的正整数序列, Peter想要那个字典序最小的序列.序列a_1, a_2, ..., a_na1,a2,...,anb_1, b_2, ..., b_nb1,b2,...,bn字典序小, 当且仅当存在一个正整数ii (1 \le i \le n)(1in)满足对于所有的kk (1 \le k < i)(1k<i)都有a_k = b_kak=bk并且a_i < b_iai<bi
说的太难理解了  简单点就是要找a数组中每个元素的最长上升子序列

解题思路:

定义一个l数组,初始化都为最大值。再循环输入的数。找到l数组中第一个比a大的数,记录下标即可。

8 num[i]1547910811dp[i]12234546i01234567a[i]INFINFINFINFINFINFINFINFans相等时替换1INFINFINFINFINFINFINF更替15INFINFINFINFINFINF更替14INFINFINFINFINFINF更替147910INFINFINF更替147810INFINFINF更替14781011INFINF


#include<cstdio>#include<algorithm>#define INF 0x3f3f3f3fusing namespace std;int dp[100050],a[100050],num[100050];int t,n;int main(){scanf("%d",&t);while(t--){scanf("%d",&n);//fill(a,a+n,INF)for(int i=1; i<=n; i++){scanf("%d",&num[i]);dp[i]=0;a[i]=INF;}for(int i=1; i<=n; i++){int ans=lower_bound(a+1, a+n+1, num[i]) - a;//得到 a 数组中的第一个比 num【i】 大的数; dp[i]=ans;a[ans]=num[i];//???将num【i】数组里的数放入(置换)充满 INF的 a 数组中  方便下次查找可以找到  }//???即使得到的 ans 和上一个相等 即 a【ans】相等也没事 因为找的是最长上升的子序列 即使相等也不影响查找 for(int i=1; i<n; i++)printf("%d ",dp[i]);printf("%d\n",dp[n]);}return 0;}//5//8//1 5 4 7 9 10 8 11 //1 2 2 3 4 5 4 6


原创粉丝点击