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
输出样例:
火车站的列车调度铁轨的结构如下图所示。
两端分别是一条入口(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
思路:
要求递减顺序...我正好看个反的.
我自己写了一发最长递增子序列 O(n^2)的 超时了,就学了一下 O(nlogn) 的 很简单
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
int dp[maxn],a;
int main()
{
int n;
scanf("%d",&n);
int len=0;
while(n--)
{
scanf("%d",&a);
if(len==0||dp[len-1]<=a) dp[len++]=a;
else
{
int l=0,r=len,mid;
while(l<=r)
{
mid=(l+r)>>1;
if(dp[mid]>a)
r=mid-1;
else
l=mid+1;
}
dp[l]=min(dp[l],a);
}
}
printf("%d\n",len);
return 0;
}
另外一种做法还是利用set大法来模拟,基于一种贪心的思想,因为要递减输出,所以对于这个列车,如果他要入队时找不到一个前面比他大的火车使其跟在后面递减的顺序的话,他就要新开一个铁路.而且基于一种贪心的思想的话,这个数肯定要跟在比他大的当中最小的那一个的后面。(这里可以使用二分查找,也可以用set)
set 当中的一个lower_bound()函数很方便.
c++ stl容器set成员函数:lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器
我们这里没有相等的情况,set还是自动排序的,就满足了我们贪心的思想,.
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
set<int>s;
int n,x;
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%d",&x);
if(s.empty())
s.insert(x);
else
{
if(s.lower_bound(x)!=s.end())
{
s.erase(s.lower_bound(x));
s.insert(x);//找到一个比此数大的使其跟在后面的,就把前面那个数删除.
}
else
s.insert(x);//否则就新开一个铁路.
}
}
printf("%d\n",s.size());//最后只需要统计剩余多少个元素就是多少个铁路.
return 0;
}