火车站的列车调度铁轨的结构如下图所示。
两端分别是一条入口(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
//思路:
//鸽笼原理(又称抽屉原理)即:将n+1个苹果放进n个抽屉里面,则至少有一个抽屉有不少于两个苹果。
//
//本题想要降序输出就是找降序子序列个数与最长上升子串的长度关系用鸽笼原理类比推导,假设有K个降序子串,最长上升子序列为L,把L看成是苹果个数,K看成是抽屉个数,如果L>K,那若将L个苹果放入K个抽屉中,必然有至少一个抽屉要有上升的序列则不能达成降序输出的目标,所以K最小为L。
下面给出队列和set集合两种解法:
方法一:队列(求最长上升字串长度)
#include <iostream>
#include <malloc.h>
#include <cstdio>
#include <cstdlib>
#define OK 1
#define FALSE 0
#define ERROR 0
#define OVERFLOW -1
#define QUEUEADD 10
#define QUEUE_INIT_SIZE 100002
using namespace std;
typedef int Status;
typedef int ElemType;
typedef struct
{
ElemType *elem;
int length;
int queuesize;
} SqQueue;
Status Init(SqQueue &L)
{
L.elem=(ElemType*)malloc(sizeof(ElemType)*QUEUE_INIT_SIZE);
if(!L.elem) exit(ERROR);
L.length=0;
L.queuesize=QUEUE_INIT_SIZE;
return OK;
}
Status Insert(SqQueue &L,int x)
{
if(L.length>=L.queuesize)//扩容
{
L.elem=(ElemType*)realloc(L.elem,sizeof(ElemType)*(QUEUE_INIT_SIZE+QUEUEADD));
if(!L.elem) exit(ERROR);
}
int f=0;
int r=L.length-1;
if(x<L.elem[f])//
{
*(L.elem)=x;
}
else if(x>L.elem[r])
{
L.length++;
L.elem[++r]=x;
}
else//二分!!!超时问题
{
while(f<r)
{
int mid=(f+r)/2;
if(L.elem[mid]<x)
f=mid+1;
else
r=mid-1;
}
L.elem[r]=x;
}
return OK;
}
int main()
{
SqQueue L;
Init(L);
int n,x;
scanf("%d",&n);
scanf("%d",&x);//第一个元素输入
L.elem[L.length]=x;
L.length++;
--n;
while(n--)
{
scanf("%d",&x);
Insert(L,x);
}
printf("%d\n",L.length);
return 0;
}
方法二:贪心思想:基于贪心,要想降序输出,就是每次进入的列车都找比他大的列车的中最小的一个跟在其后头降序输出,实践到算法就是每次都找到那个比他大最小的车插进他后面再将他删除。
set(用到函数:lower_bound()(函数用法:c++ stl容器set成员函数:lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器)
#include<bits/stdc++.h>
using namespace std;
set<int>s;
int n,x;
int main()
{
scanf("%d",&n);
--n;
s.insert(x);
while(n--)
{
scanf("%d",&x);
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;
}