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

传送门: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)表示那个字典序最小的序列.
输入样例
3
1
10
5
5 4 3 2 1
3
1 3 5
输出样例
1
1 1 1 1 1
1 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]1547910811
dp[i]12234546
i01234567
a[i]INFINFINFINFINFINFINFINF
ans相等时替换1INFINFINFINFINFINFINF
更替15INFINFINFINFINFINF
更替14INFINFINFINFINFINF
更替147910INFINFINF
更替147810INFINFINF
更替14781011INFINF



#include<cstdio>
#include<algorithm>
#define INF 0x3f3f3f3f
using 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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值