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;
}

参考了: 芋圆西米露 的博客。

 

posted @ 2020-04-10 15:00  Kanoon  阅读(167)  评论(0编辑  收藏  举报