【题目】
题目描述:
有 N 辆列车,标记为 1,2,3,…,N。它们按照一定的次序进站,站台共有 K 个轨道,轨道遵从先进先出的原则。列车进入站台内的轨道后可以等待任意时间后出站,且所有列车不可后退。现在要使出站的顺序变为 N,N-1,N-2,…,1,询问 K 的最小值是多少。
例如上图中进站的顺序为 1,3,2,4,8,6,9,5,7,则出站的顺序变为 9,8,7,6,5,4,3,2,1。
输入格式:
输入共 2 行。
第 1 行包含 1 个正整数 N ,表示 N 辆列车。
第 2 行包含 N 个正整数,为 1 至 N 的一个排列,表示进站次序。
输出格式:
输出共 1 行,包含 1 个整数,表示站台内轨道数 K 的最小值。
样例数据:
输入
3
1 2 3输出
3
输入
9
1 3 2 4 8 6 9 5 7输出
5
备注:
【数据规模与约定】
对于 30% 的数据,N ≤ 10;
对于 70% 的数据,N ≤ 2000;
对于 100% 的数据,N ≤ 100000。
【分析】
第一次 A 第二题
感觉这道题有点像最长下降子序列,听说大佬们还用这个方法做出来了,这里本蒟蒻说一下贪心的算法
对于每一个轨道,由于是先进先出,出站的顺序又是从 N 到 1,很明显,每一个轨道后进入的列车的编号一定比前面的小
我们可以把原问题转换成,将这个序列分割成几个下降的序列,且数量要尽可能少
例如样例数据 2,我们可以把它拆成(1),(3,2),(4),(8,6,5),(9,7)
我们用一个数组记录每个轨道进来的最后一个列车的编号,每次新进来一辆列车,就找数组中大于它的最小的那个轨道,将它加到这个轨道中。这样的话,我们就能保证数组中的数单调递增,就可以用二分
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;
int a[N],track[N];
int main()
{
// freopen("manage.in","r",stdin);
// freopen("manage.out","w",stdout);
int n,i,l,r,mid,k=1;
scanf("%d",&n);
for(i=1;i<=n;++i)
scanf("%d",&a[i]);
track[1]=a[1];
for(i=2;i<=n;++i)
{
l=1,r=k;
if(track[k]<a[i])
{
k++;
track[k]=a[i];
continue;
}
while(l<r)
{
mid=(l+r)>>1;
if(track[mid]>a[i]) r=mid;
else l=mid+1;
}
track[l]=a[i];
}
printf("%d",k);
// fclose(stdin);
// fclose(stdout);
return 0;
}