1023: 巨人排队
题目描述
巨人国的小学生放假了,老师要给小朋友们排队了。可是这个老师有强迫症,一定要路队上的小朋友按照身高从高到矮排序(也就是排在前面的不能比后面的矮)。小朋友呢也很调皮,一旦老师给他排好队就不愿意动了。这个时候小朋友们一个一个的从教室里出来了,每个小朋友一出来老师就要给小朋友安排好位置。请问老师最少要给小朋友排几条路队呢?
输入
对于每组数据,第一行一个数n,表示小朋友总数量(1<=n<=100000)
第二行n个整数,表示小朋友身高,身高不超过30000
输出
对于每组数据,输出一个整数,表示最少的路队数
样例输入
8
389 207 155 300 299 170 158 65
样例输出
2
思路 1
1.排新队的条件是当前要排的小朋友比所有已有队伍的最后一位同学都高;
2.当有多条队伍可以排当前小朋友时应该使得小朋友排进身高差(当前小朋友与队伍中最后一位小朋友的身高的差值)最小的那一队。
综上,若使用一个动态数组 vec 来存储队伍,则可以只存储队伍最后一位小朋友的身高,且由 1 可知 vec 必定是递增的,则:
1.小朋友身高 h 大于 vec 最后一个元素时,需要新的队伍,vec.push_back(h);
2.小朋友身高 h 小于 vec 最后一个元素时,从头到尾遍历 vec 数组,找到第一个 vec[i] >= h 的元素,更新此元素为 h 即可。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n, x;
while(scanf("%d", &n) != EOF)
{
vector<int> vec;
scanf("%d", &x);
vec.push_back(x);
for(int i = 1; i < n; i++)
{
scanf("%d", &x);
if(x > *(vec.end() - 1))
vec.push_back(x);
else
{
for(int j = 0; j < (int)vec.size(); j++)
{
if(vec[j] >= x )
{
vec[j] = x;
break;
}
}
}
}
printf("%d\n", (int)vec.size());
}
return 0;
}
思路 2
使用 set 来存储每一队伍最后一个同学的身高,则
1.set 中的元素单调不减;
2.每次来了新的小朋友(身高 h )仅需使用 lower_bound(h) 查找队列中是否有合适的队伍,由于 1 保证了 lower_bound(h) 所找到的必定是身高差最小的队伍,若没有合适的队伍则直接 insert(h)。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n, x;
while(scanf("%d", &n) != EOF)
{
set<int> s;
for(int i = 0; i < n; i++)
{
scanf("%d", &x);
if(s.lower_bound(x) != s.end())
s.erase(s.lower_bound(x));
s.insert(x);
}
printf("%d\n", s.size());
}
return 0;
}