题目:
火车站的列车调度铁轨的结构如下图所示。
两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?
输入格式:
输入第一行给出一个整数N (2 ≤ N ≤10^5),下一行给出从1到N的整数序号的一个重排列。数字间以空格分隔。
输出格式:
在一行中输出可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。
输入样例:
9
8 4 2 5 3 9 1 6 7
结尾无空行
输出样例:
4
结尾无空行
思路:
/*
模拟队列的先进先出,设数组res看作是轨道,下标对应是第几条轨道;
题目要求按照序号的递减顺序从出口离开,那么每次对轨道数组的更新都要找到既满足比轨道中现存的元素小也要满足轨道下标尽可能的小;
在查找过程中,不能使用for循环,o(n)的时间复杂度会在最后的测试点被卡住,需要使用二分查找法。
但在二分查找法中,不能一找到res[mid] > a[i]就break, 一定要全部循环一遍,争取找到满足条件的轨道下标最小值。
flag条件判断是否需要增加轨道数。
为了方便,数组所有下标都是从1开始的。
*/
代码:
#include <stdio.h>
#define maxsize 100005
int a[maxsize];
int res[maxsize];
int main()
{
int n;
scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%d", &a[i]);
res[1] = a[1];//第一条轨道一定存储第一个序号
int cnt = 1;//默认轨道数为一条
for(int i=2; i<=n; i++)
{
int flag = 1, index = 0;
// 使用二分查找,否则会被卡时间
int left=1, right=cnt;
while (left <= right)
{
int mid = (left + right) / 2;
if(res[mid] > a[i])
{
flag = 0;
index = mid;
right = mid - 1;
}else left = mid + 1;
}
if(flag) res[++cnt] =a[i];
else res[index] = a[i];
}
printf("%d", cnt);
return 0;
}