[CSP-S 2021] 廊桥分配
题目描述
当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位。乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折。然而,因为廊桥的数量有限,所以这样的愿望不总是能实现。
机场分为国内区和国际区,国内航班飞机只能停靠在国内区,国际航班飞机只能停靠在国际区。一部分廊桥属于国内区,其余的廊桥属于国际区。
L 市新建了一座机场,一共有 $n$ 个廊桥。该机场决定,廊桥的使用遵循“先到先得”的原则,即每架飞机抵达后,如果相应的区(国内/国际)还有空闲的廊桥,就停靠在廊桥,否则停靠在远机位(假设远机位的数量充足)。该机场只有一条跑道,因此不存在两架飞机同时抵达的情况。
现给定未来一段时间飞机的抵达、离开时刻,请你负责将 $n$ 个廊桥分配给国内区和国际区,使停靠廊桥的飞机数量最多。
输入格式
输入的第一行,包含三个正整数 $n, m_1, m_2$,分别表示廊桥的个数、国内航班飞机的数量、国际航班飞机的数量。
接下来 $m_1$ 行,是国内航班的信息,第 $i$ 行包含两个正整数 $a{1, i}, b{1, i}$,分别表示一架国内航班飞机的抵达、离开时刻。
接下来 $m_2$ 行,是国际航班的信息,第 $i$ 行包含两个正整数 $a{2, i}, b{2, i}$,分别表示一架国际航班飞机的抵达、离开时刻。
每行的多个整数由空格分隔。
输出格式
输出一个正整数,表示能够停靠廊桥的飞机数量的最大值。
样例 #1
样例输入 #1
3 5 4
1 5
3 8
6 10
9 14
13 18
2 11
4 15
7 17
12 16
样例输出 #1
7
样例 #2
样例输入 #2
2 4 6
20 30
40 50
21 22
41 42
1 19
2 18
3 4
5 6
7 8
9 10
样例输出 #2
4
样例 #3
样例输入 #3
见附件中的 airport/airport3.in
样例输出 #3
见附件中的 airport/airport3.ans
提示
【样例解释 #1】

在图中,我们用抵达、离开时刻的数对来代表一架飞机,如 $(1, 5)$ 表示时刻 $1$ 抵达、时刻 $5$ 离开的飞机;用 $\surd$ 表示该飞机停靠在廊桥,用 $\times$ 表示该飞机停靠在远机位。
我们以表格中阴影部分的计算方式为例,说明该表的含义。在这一部分中,国际区有 $2$ 个廊桥,$4$ 架国际航班飞机依如下次序抵达:
- 首先 $(2, 11)$ 在时刻 $2$ 抵达,停靠在廊桥。
- 然后 $(4, 15)$ 在时刻 $4$ 抵达,停靠在另一个廊桥。
- 接着 $(7, 17)$ 在时刻 $7$ 抵达,这时前 $2$ 架飞机都还没离开、都还占用着廊桥,而国际区只有 $2$ 个廊桥,所以只能停靠远机位。
- 最后 $(12, 16)$ 在时刻 $12$ 抵达,这时 $(2, 11)$ 这架飞机已经离开,所以有 $1$ 个空闲的廊桥,该飞机可以停靠在廊桥。
根据表格中的计算结果,当国内区分配 $2$ 个廊桥、国际区分配 $1$ 个廊桥时,停靠廊桥的飞机数量最多,一共 $7$ 架。
【样例解释 #2】
当国内区分配 $2$ 个廊桥、国际区分配 $0$ 个廊桥时,停靠廊桥的飞机数量最多,一共 $4$ 架,即所有的国内航班飞机都能停靠在廊桥。
需要注意的是,本题中廊桥的使用遵循“先到先得”的原则,如果国际区只有 $1$ 个廊桥,那么将被飞机 $(1, 19)$ 占用,而不会被 $(3, 4)$、$(5, 6)$、$(7, 8)$、$(9, 10)$ 这 $4$ 架飞机先后使用。
【数据范围】
对于 $20 \%$ 的数据,$n \le 100$,$m_1 + m_2 \le 100$。
对于 $40 \%$ 的数据,$n \le 5000$,$m_1 + m_2 \le 5000$。
对于 $100 \%$ 的数据,$1 \le n \le {10} ^ 5$,$m_1, m_2 \ge 1$,$m_1 + m_2 \le {10} ^ 5$,所有 $a{1, i}, b{1, i}, a{2, i}, b{2, i}$ 为数值不超过 ${10} ^ 8$ 的互不相同的正整数,且保证对于每个 $i \in [1, m_1]$,都有 $a{1, i} < b{1, i}$,以及对于每个 $i \in [1, m_2]$,都有 $a{2, i} < b{2, i}$。
【感谢 hack 数据提供】
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <math.h>
#define int long long
using namespace std;
struct Flight {
int start_time;
int end_time;
int type; // 1: 国内, 2: 国际
};
struct CompareFlights {
bool operator()(Flight a, Flight b) {
return a.start_time > b.start_time;
}
};
signed main() {
int lang_num, flight_guo, flight_wai;
cin >> lang_num >> flight_guo >> flight_wai;
priority_queue<Flight, vector<Flight>, CompareFlights> minHeap_guo;
priority_queue<Flight, vector<Flight>, CompareFlights> minHeap_wai;
// 输入国内航班信息
for (int i = 0; i < flight_guo; i++) {
int start_time, end_time;
cin >> start_time >> end_time;
Flight new_flight = { start_time, end_time, 1 };
minHeap_guo.push(new_flight);
}
// 输入国际航班信息
for (int i = 0; i < flight_wai; i++) {
int start_time, end_time;
cin >> start_time >> end_time;
Flight new_flight = { start_time, end_time, 2 };
minHeap_wai.push(new_flight);
}
vector<int> time_guo(flight_guo, 0);
vector<int> count_guo(flight_guo, 0);
for (int i = 0; i < flight_guo; i++) {
int number = 0;
while (true) {
if (minHeap_guo.top().start_time >= time_guo[number]) {
time_guo[number] = minHeap_guo.top().end_time;
minHeap_guo.pop();
count_guo[number]++;
break;
}
number++;
}
}
for (int i = 1; i <flight_guo; i++)
{
count_guo[i] = count_guo[i] + count_guo[i - 1];
}
count_guo.insert(count_guo.begin(), 0);
vector<int> time_wai(flight_wai + 1, 0);
vector<int> count_wai(flight_wai + 1, 0);
for (int i = 0; i < flight_wai; i++) {
int number = 0;
while (true) {
if (minHeap_wai.top().start_time >= time_wai[number]) {
time_wai[number] = minHeap_wai.top().end_time;
minHeap_wai.pop();
count_wai[number]++;
break;
}
number++;
}
}
for (int i = 1; i <flight_wai; i++)
{
count_wai[i] = count_wai[i] + count_wai[i - 1];
}
count_wai.insert(count_wai.begin(), 0);
//输出结果
//for (int i = 0; i < flight_guo; i++) {
// cout << count_guo[i] << " ";
//}
//cout << endl;
//for (int i = 0; i < flight_wai; i++) {
// cout << count_wai[i] << " ";
//}
//cout << endl;
int max_num = 0;
for (int i = 0; i <= lang_num; i++)
{
int num1 = i;
int num2 = lang_num - i;
if (num1>flight_guo)
{
num1 = flight_guo;
}
if (num2 > flight_wai)
{
num2 = flight_wai;
}
int sum = count_wai[num2] + count_guo[num1];
if (sum>max_num)
{
max_num = sum;
}
}
cout << max_num;
return 0;
}