GPLT L2-014 列车调度(二分,贪心)
题目链接:L2-014 列车调度
题意
如果一个排列最终可以按照降序输出,至少需要多少个队列来存储。
思路
如果当前数比之前的数都大,则需要新开一个队列,否则每次替换掉第一个大于它的数。
证明
我们担心的是如果将一个较小的数接在一个较大的数后面,之后更长的递减序列会无法接在较大的数后面,但如果我们想要将之后更长的递减序列接在较大的数后面,我们就必须为当前较小的数新开一个队列,因此无论如何我们都至少需要两个队列,所以我们可以贪心地将每个数接在第一个大于它的数后面,相当于与接在较大数后的递减序列交换了位置。
Tips
std::lower_bound 和 std::upper_bound 是在有序数组中线性二分查询的,对于内部实现是树形结构的 set、map,应该使用二者自带的函数。
代码
树形二分查找:
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; set<int> st; for (int i = 0; i < n; i++) { int x; cin >> x; auto it = st.upper_bound(x); if (it == st.end()) { st.insert(x); } else { st.erase(it); st.insert(x); } } cout << st.size(); }
线性二分查找:
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; int a[n], p = 0; for (int i = 0; i < n; i++) { int x; cin >> x; if (p == 0 || x > a[p - 1]) { a[p++] = x; } else { int pos = upper_bound(a, a + p, x) - a; a[pos] = x; } } cout << p; }
参考了: 芋圆西米露 的博客。