CSP-S 2021 T1廊桥分配

CSP-S 2021 T1廊桥分配

枚举分配给国内航班和国外航班的廊桥数量,若分配给国内机场 i i i个廊桥,则国外机场就有 n − i n-i n−i个廊桥,在此基础上分别判断两边各能通过多少飞机。用一个小根堆存储飞机离开的时间,枚举到一个飞机到达的时间时,将小根堆中的这个到达时间之前的点弹出,复杂度 O ( n ( m 1 + m 2 ) ) O(n(m1+m2)) O(n(m1+m2)),可以通过 n ≤ 5000 , m 1 + m 2 ≤ 5000 n\leq5000,m_1+m_2\leq5000 n≤5000,m1+m2≤5000的数据,拿到 40 40 40分(实际 45 45 45分)。

cpp 复制代码
#include <bits/stdc++.h>
#define A 100010

using namespace std;
struct node {
	int a, b;
	friend bool operator < (const node x, const node y) {
		if (x.a != y.a) return x.a < y.a;
		else return x.b < y.b;
	}
}e1[A], e2[A];
int n, m1, m2, ans;

int main(int argc, char const *argv[]) {
	cin >> n >> m1 >> m2;
	for (int i = 1; i <= m1; i++) {
		scanf("%d%d", &e1[i].a, &e1[i].b);
	}
	for (int i = 1; i <= m2; i++) {
		scanf("%d%d", &e2[i].a, &e2[i].b);
	}
	sort(e1 + 1, e1 + m1 + 1);
	sort(e2 + 1, e2 + m2 + 1);
	priority_queue<int, vector<int>, greater<int> > q;
	for (int i = 0; i <= n; i++) {
		int ti = i, tj = n - i;
		int sum1 = 0, sum2 = 0;
		if (ti == 0) {
			sum1 = 0;
		}
		else {
			while (q.size()) q.pop();
			for (int j = 1; j <= m1; j++) {
				while (!q.empty() and e1[j].a >= q.top()) q.pop(), ti++;
				if (ti - 1 >= 0) {
					sum1++;
					q.push(e1[j].b);
					ti--;
				}
			}
		}
		if (tj == 0) {
			sum2 = 0;
		}
		else {
			while (q.size()) q.pop();
			for (int j = 1; j <= m2; j++) {
				while (!q.empty() and e2[j].a >= q.top()) q.pop(), tj++;
				if (tj - 1 >= 0) {
					sum2++;
					q.push(e2[j].b);
					tj--;
				}
			}
		}
		ans = max(ans, sum1 + sum2);
	}
	cout << ans << endl;
}

假设已经有 n n n架飞机通过 m m m个廊桥完成了降落,如果此时来了第 n + 1 n+1 n+1架飞机,那么这架飞机不会影响之前 n n n架飞机的降落情况(具体降落在哪个廊桥)。所以我们可以模拟出每架飞机降落时所抵达的廊桥编号,同时也就知道了每个廊桥降落过飞机的数量。

例如编号为 1 1 1的廊桥降落过 3 3 3架飞机,编号为 2 2 2的廊桥降落过 3 3 3架飞机,编号为 3 3 3的廊桥降落过 2 2 2架飞机,在这种情况下如果有 2 2 2个廊桥,那么可以停留的飞机数量就是 3 + 3 = 6 3+3=6 3+3=6;如果有 3 3 3个廊桥,可以停留的飞机数量就是 3 + 3 + 2 = 8 3+3+2=8 3+3+2=8。

具体实现时,使用一个优先队列 q q q表示某家飞机的到达时间和离开时间,与部分分做法表示的含义相同,但还需要加一个所停靠廊桥的编号,因此可以使用pair<int,int>来存储。另一个优先队列 q q qq qq表示空闲的廊桥编号,初始时 n n n个廊桥都空闲,所以将 n n n个廊桥都加入优先队列 q q qq qq。

cpp 复制代码
#include <bits/stdc++.h>
#define A 100010
#define pi pair<int, int>

using namespace std;
struct node {
	int a, b;
	friend bool operator < (const node x, const node y) {
		if (x.a != y.a) return x.a < y.a;
		else return x.b < y.b;
	}
}e1[A], e2[A];
int n, m1, m2, ans, f1[A], f2[A];

int main(int argc, char const *argv[]) {
	cin >> n >> m1 >> m2;
	for (int i = 1; i <= m1; i++) {
		scanf("%d%d", &e1[i].a, &e1[i].b);
	}
	for (int i = 1; i <= m2; i++) {
		scanf("%d%d", &e2[i].a, &e2[i].b);
	}
	sort(e1 + 1, e1 + m1 + 1);
	sort(e2 + 1, e2 + m2 + 1);
	priority_queue<pi, vector<pi>, greater<pi> > q;
	priority_queue<int, vector<int>, greater<int> > qq;
	for (int i = 1; i <= n; i++) qq.push(i);
	for (int i = 1; i <= m1; i++) {
		while (!q.empty() and e1[i].a >= q.top().first) {
			qq.push(q.top().second);
			q.pop();
		}
		if (qq.empty()) continue;
		int top = qq.top();
		qq.pop();
		f1[top]++;
		q.push(make_pair(e1[i].b, top));
	}
	for (int i = 1; i <= n; i++) f1[i] += f1[i - 1];

	while (!q.empty()) q.pop();
	while (!qq.empty()) qq.pop();

	for (int i = 1; i <= n; i++) qq.push(i);
	for (int i = 1; i <= m2; i++) {
		while (!q.empty() and e2[i].a >= q.top().first) {
			qq.push(q.top().second);
			q.pop();
		}
		if (qq.empty()) continue;
		int top = qq.top();
		qq.pop();
		f2[top]++;
		q.push(make_pair(e2[i].b, top));
	}
	for (int i = 1; i <= n; i++) f2[i] += f2[i - 1];
	for (int i = 0; i <= n; i++)
		ans = max(ans, f1[i] + f2[n - i]);
	cout << ans << endl;
}
相关推荐
格林威5 小时前
常规线扫描镜头有哪些类型?能做什么?
人工智能·深度学习·数码相机·算法·计算机视觉·视觉检测·工业镜头
程序员莫小特7 小时前
老题新解|大整数加法
数据结构·c++·算法
过往入尘土8 小时前
服务端与客户端的简单链接
人工智能·python·算法·pycharm·大模型
zycoder.8 小时前
力扣面试经典150题day1第一题(lc88),第二题(lc27)
算法·leetcode·面试
蒙奇D索大8 小时前
【数据结构】考研数据结构核心考点:二叉排序树(BST)全方位详解与代码实现
数据结构·笔记·学习·考研·算法·改行学it
智驱力人工智能9 小时前
工厂抽烟检测系统 智能化安全管控新方案 加油站吸烟检测技术 吸烟行为智能监测
人工智能·算法·安全·边缘计算·抽烟检测算法·工厂抽烟检测系统·吸烟监测
程序员爱钓鱼9 小时前
Go语言实战案例——进阶与部署篇:编写Makefile自动构建Go项目
后端·算法·go
_Power_Y10 小时前
Java面试常用算法api速刷
java·算法·面试
艾醒(AiXing-w)10 小时前
大模型面试题剖析:模型微调中冷启动与热启动的概念、阶段与实例解析
人工智能·深度学习·算法·语言模型·自然语言处理
天选之女wow10 小时前
【代码随想录算法训练营——Day32】动态规划——509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯
算法·leetcode·动态规划