问题分析
题目要求将一列火车车厢按编号递减的顺序调度到多个轨道上,每个轨道上的车厢必须严格递减。求最少需要多少条轨道。
关键思路:
维护每个轨道的末尾车厢编号,使得这些编号按递增顺序排列。每次处理新的车厢时,找到可以接在末尾的最小可能轨道,从而最小化轨道数量。这转化为求原序列最长递增子序列的长度,根据Dilworth定理,最少轨道数等于最长递增子序列的长度。
关键代码解析
1.二分查找定位插入位置
int pos = upper_bound(q.begin(), q.end(), a) - q.begin();
功能:在递增数组q中找到第一个大于a的元素位置。 原理:若a可接在某轨道末尾(即该末尾> a),选择大于a且最接近的末尾轨道,以保持轨道数量最少。upper_bound高效定位插入点。 示例:假设q = [2, 5, 7, 9],a = 6,upper_bound找到7的位置2,pos = 2。之所以选7不选9是因为7>6,且最接近6,如果选9相当于9所在的那条轨道浪费了7和8两个编号位置。
2.开新轨道或替换末尾
if (pos >= q.size()) q.push_back(a);
else q[pos] = a;
开新轨道:若a大于所有末尾(pos越界),则a必须作为新轨道末尾,如q = [2, 5, 7],a = 9,新轨道q = [2,5,7,9]。 替换末尾:若找到合适轨道,将a替换该轨道末尾,保持q递增。如q = [2,5,7],a =6替换为q = [2,5,6],允许后续更小的数接在5之后。 示例:q = [3,5,8],处理a=4:pos = 1。
3.维护递增数组优化性能
每次替换或添加元素后,数组q保持严格递增,确保后续upper_bound的正确性。替换策略类似求最长递增子序列的贪心+二分优化。
整体示例
输入序列:8 4 2 5 3 9 处理过程:
8 → q = [8] 4 → 替换8 → q = [4] 2 → 替换4 → q = [2] 5 → 开新轨道 → q = [2,5] 3 → 替换5 → q = [2,3] 9 → 开新轨道 → q = [2,3,9] 最终轨道数:3(最长递增子序列2,3,9或4,5,9等,长度3)
结论
通过维护递增的轨道末尾数组,每次高效定位插入点,确保轨道数最少。该算法时间复杂度为O(n log n),适用于大规模数据,正确性由Dilworth定理保证。 详细代码请参见提交记录
[参考代码](https://ykj.cpolar.cn/submission/602906)