[CSP-S 2021] 廊桥分配题解

廊桥分配

题目背景

CSP-S 2021 T1

题目描述

L L L 市新建了一座机场,一共有 n n n 个廊桥。该机场决定,廊桥的使用遵循“先到先得”的原则,即每架飞机抵达后,如果相应的区(国内/国际)还有空闲的廊桥,就停靠在廊桥,否则停靠在远机位(假设远机位的数量充足)。该机场只有一条跑道,因此不存在两架飞机同时抵达的情况。现给定未来一段时间飞机的抵达、离开时刻,请你负责将 n n n 个廊桥分配给国内区和国际区,使停靠廊桥的飞机数量最多

解题方法

  f 1 ,   i \ f_{1,\ i}  f1, i 表示国内航班有   i \ i  i 座廊桥时,能停靠的航班数量最大值。
同理, f 2 ,   i f_{2,\ i} f2, i 表示国际航班有   i \ i  i 座廊桥时,能停靠的航班数量最大值。
∴ \therefore 答案即为 max ⁡ i = 0 n ( f 1 ,   i +   f 2 ,   n − i ) \max\limits_{i=0}^{n} (f_{1,\ i}+\ f_{2,\ n - i}) i=0maxn(f1, i+ f2, ni)
然后分别处理   f 1 \ f_1  f1   f 2 \ f_2  f2,分别从   1 ∼ m 1 \ 1 \sim m_1  1m1   1 ∼ m 2 \ 1 \sim m_2  1m2 处理。每次处理完一次,只需在前一项上修改,可以用   s e t \ set  set 维护。

代码实现

#include 
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 7;
int n, m1, m2, ans;
int f[3][N];
set<PII> domes, intern;
void Airport(set<PII> st, int* f)
{
	for (int i = 1; i <= n; i++) {
		vector<PII> vec;
		f[i] += f[i - 1];
		for (set<PII>::iterator it = st.begin(); it != st.end(); it = st.lower_bound({ it->second, 0 })) {
			f[i]++;
			vec.push_back({ it->first, it->second });
		}
		for (auto it : vec)
			st.erase(it);
	}
}
inline int read()
{
	register int s = 0, w = 1;
	register char ch = getchar();
	while (ch < '0' or ch > '9') { if (ch == '-') w = -1; ch = getchar(); }
	while (ch >= '0' and ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
	return s * w;
}
int main()
{
	n = read(), m1 = read(), m2 = read();
	for (int i = 1; i <= m1; i++) {
		int arrive = read(), leave = read();
		domes.insert({ arrive, leave });
	}
	for (int i = 1; i <= m2; i++) {
		int arrive = read(), leave = read();
		intern.insert({ arrive, leave });
	}
	Airport(domes, f[1]);
	Airport(intern, f[2]);
	for (int i = 0; i <= n; i++)
		ans = max(ans, f[1][i] + f[2][n - i]);
	printf("%d\n", ans);
	return 0;
}

你可能感兴趣的:(题解,c++,算法,数据结构,动态规划)