1 条题解
-
2
每个飞机的抵达和离开可以看成是一个线段,首先有一个朴素的思路,枚举廊桥的数量,接下来对于每做到达的飞机,由于采取先到先得的策略,所以随便挑一个空闲的廊桥分配进去就可以了。
如果这样去做还需要枚举廊桥数量去计算复杂度是比较高的。我们有一种贪心的策略,即对于不得不去一个全新的廊桥的时候,再分配过去,即初始只有一个廊桥,对于接下来到达的飞机如果可以安排到第一个就安排到第一个,不可以则新开一个廊桥。那么对于后续的廊桥都是如此的。所以本题更像是一个模拟题
对于国内航班来说,我们预处理给每个廊桥分配飞机的最多数量
对于国际航班也预处理一个数组
假如枚举给国内分配 个,则国内的停靠数量就是 国际就是
我们需要维护一个占用的廊桥集合,也需要维护一个空闲的廊桥集合,对于此时新到达一架飞机,它的到达时间假如为 那么首先我们需要把占用集合中离开时间 小于 的飞机转移到空闲集合,这一部分可以采取小根堆来做。
#include <bits/stdc++.h> #define ll long long #define p pair<int, int> #define x first #define y second using namespace std; const int N = 1e5 + 5; int n, m1, m2; p a[N], b[N]; // 国内和国际 int s1[N], s2[N], res; void solve(p a[], int s[], int m) { sort(a + 1, a + m + 1); priority_queue<p, vector<p>, greater<p>> q1; priority_queue<int, vector<int>, greater<int>> q2;//空闲集合 for (int i = 1; i <= n; i++) q2.push(i);// 初始n个廊桥都空闲 for (int i = 1; i <= m; i++) { int st = a[i].x; // 当前飞机的抵达时间 while (q1.size() && q1.top().x < st) // 已经占用的廊桥可以腾出位置 { q2.push(q1.top().y); q1.pop(); } if (q2.empty()) continue; // 无空闲跳过 int now = q2.top(); q2.pop(); q1.push({a[i].y, now}); // 记录当前飞机的离开时间和占用的廊桥编号 s[now]++; } for (int i = 2; i <= n; i++) s[i] += s[i - 1]; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m1 >> m2; for (int i = 1; i <= m1; i++) cin >> a[i].x >> a[i].y; for (int i = 1; i <= m2; i++) cin >> b[i].x >> b[i].y; solve(a, s1, m1), solve(b, s2, m2); for (int i = 0; i <= n; i++) { res = max(res, s1[i] + s2[n - i]); } cout << res; return 0; }
- 1
信息
- ID
- 1365
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 68
- 已通过
- 32
- 上传者