参考处-依此补充了一些内容 原题1-洛谷P7913 原题2-一本通T2078
这道题数据范围达到了,用暴力破解指定不行,但我们可以仿照思路,进行修改优化。我们先不管廊桥数量,维护两个优先队列,每一个飞机到达,我们就给他最小的廊桥进行分配。加上廊桥数,跟刚才同理,如果超过了n个廊桥,那么我们就把第n+1个廊桥看作远机位,代码实现直接continue即可。
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// 定义pair<int, int>的别名,用于存储离开时间和廊桥编号
typedef pair<int, int> pii;
// 定义航班结构体,存储航班的到达时间和离开时间
struct range {
int x, y; // x: 到达时间,y: 离开时间
} a[100005], b[100005]; // a: 国内航班,b: 国际航班
// res1: 国内航班使用i个廊桥时能停靠的飞机数量
// res2: 国际航班使用i个廊桥时能停靠的飞机数量
int res1[100005], res2[100005];
int n; // 廊桥总数
// 比较函数,用于按照到达时间排序
bool cmp(const range& a, const range& b){
return a.x < b.x; // 按到达时间升序排列
}
// 计算函数:计算在给定航班数据下,使用不同数量廊桥能停靠的飞机数量
// t: 航班数组,m: 航班数量,res: 结果数组
void calc(range* t, int m, int* res){
// lq: 最小堆,存储正在使用的廊桥的离开时间和廊桥编号
// 堆顶是离开时间最早的廊桥
priority_queue<pii, vector<pii>, greater<pii> > lq;
// wq: 最小堆,存储当前空闲的廊桥编号
priority_queue<int, vector<int>, greater<int> > wq;
// 初始化所有廊桥为空闲状态
for (int i = 1; i <= n; i++) wq.push(i);
// 处理每个航班
for (int i = 1; i <= m; i++) {
// 检查是否有航班已经离开,释放廊桥
// 如果当前航班的到达时间 >= 堆顶航班的离开时间,说明该廊桥已空闲
while (!lq.empty() && t[i].x >= lq.top().first) {
wq.push(lq.top().second); // 将廊桥编号加入空闲队列
lq.pop(); // 弹出已离开的航班
}
// 如果没有空闲廊桥,跳过当前航班
if (wq.empty()) continue;
// 分配廊桥:取编号最小的空闲廊桥
int dest = wq.top();
wq.pop();
// 记录该廊桥停靠的飞机数量+1
res[dest]++;
// 将当前航班加入使用中的廊桥队列,记录离开时间和使用的廊桥编号
lq.push(make_pair(t[i].y, dest));
}
// 计算前缀和:res[i]表示使用i个廊桥时能停靠的飞机总数
for (int i = 1; i <= n; i++) res[i] += res[i - 1];
}
int main(){
int m1, m2; // m1: 国内航班数量,m2: 国际航班数量
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;
// 按到达时间排序航班
sort(a + 1, a + m1 + 1, cmp);
sort(b + 1, b + m2 + 1, cmp);
// 计算国内和国际航班的结果
calc(a, m1, res1);
calc(b, m2, res2);
// 寻找最优分配方案:国内使用i个,国际使用n-i个
int ans = 0;
for (int i = 0; i <= n; i++)
ans = max(ans, res1[i] + res2[n - i]);
// 输出结果
cout << ans << endl;
return 0;
}

1087

被折叠的 条评论
为什么被折叠?



