package A类有价值的回顾的;
//(LIS)
/*
* 5-10 列车调度 (25分)
火车站的列车调度铁轨的结构如下图所示。
两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?
输入格式:
输入第一行给出一个整数N (2 \le≤ N \le 10^5≤10
5
),下一行给出从1到N的整数序号的一个重排列。数字间以空格分隔。
输出格式:
在一行中输出可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。
输入样例:
9
8 4 2 5 3 9 1 6 7
输出样例:
4
*/
import java.io.BufferedInputStream;
import java.util.Scanner;
public class 最长上升子序列 {
public static void main(String[] args) {
int[] dp = new int[100];//c[i]存储的是子序列长度为i的序列最后一个值(实际上子序列长度为i的子序列有多个
Scanner sc = new Scanner(new BufferedInputStream(System.in));
int n = sc.nextInt();
int len = 0;
/*8 4 2 5 3 9 1 6 7 (3.5) 思路:因为另辟一队的原因是当前的a(包含了顺序)太大不能插入上一队的队尾,下一队的对头一定大于上一队的队尾
*
* 1 2 4 8 //输入8之后,以8结尾的递增子序列就只有1位,因为4前面是大于4的,所以以4结尾的上升子序列只有4
* 3 5 //如果此时加入一个3.5,过程是这样的:3.5之所以不插入3后面是因为比3大,此时直接借用3储存的的dp就可以了(而3插入5后面是因为3比1大)
* (3.5)6 9
* 7
*/
while(n != 0){
int a = sc.nextInt();
if(len==0||dp[len-1]<=a)//也就是说当前的a比较大,不能够插入队尾,只能另辟一队
dp[len++] = a;
else{
int l=0,r=len,mid;//这是一个二分查找,寻找能够插入队尾的那一队
while(l<=r){
mid = (l+r)>>1;//相当于/2
if(dp[mid]>a)
r = mid-1;
else
l = mid+1;
}
dp[l] = Math.min(dp[l], a);//更新队尾
}
n--;
}
for(int i=0;i<len;i++){
System.out.print(dp[i]+" ");
}System.out.println();
System.out.println(len);
}
}
最长上升子序列.java
最新推荐文章于 2022-03-05 20:10:06 发布