Solution P7914 [CSP-S2021] 廊桥分配
题意
给你 \(n\) 个廊桥,有两个区的飞机,飞机先到先得,问如何分配使得能够停靠廊桥的飞机数量的最大,输出能够停靠廊桥的飞机数量的最大值。
Solution
让我们先忽略廊桥数量的限制来安排航班。我们维护一个空闲的廊桥队列,每到达一架航班,就给它安排编号最小的廊桥供其使用。
就是只要有飞机进来,如果没有空余的廊桥就直接加一个,即不考虑廊桥数量,然后分别记录每个廊桥所能停靠的最大飞机数,然后做一个前缀和,用 \(f_i\) 表示有 \(i\) 个廊桥时所能停靠的飞机数,最后枚举分配给国内区和国际区的廊桥数,即 \(ans = \max(f_i,f_{n-i})\) .
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m1, m2, f[3][N], T[N], ans;
struct node
{
int a, b;
}pl[3][N];
bool cmp(node x, node y)
{
return x.a < y.a;
}
void work(int m, int k)
{
sort(pl[k] + 1, pl[k] + m + 1, cmp);
memset(T, 0, sizeof(T));
for(int i = 1; i <= m; i++)
{
int t = 1;
while(t <= n)
if(pl[k][i].a > T[t])
{
T[t] = pl[k][i].b;
f[k][t]++;
break;
}
else t++;
}
}
int main()
{
scanf("%d%d%d", &n, &m1, &m2);
for(int i = 1; i <= m1; i++)
scanf("%d%d", &pl[1][i].a, &pl[1][i].b);
for(int i = 1; i <= m2; i++)
scanf("%d%d", &pl[2][i].a, &pl[2][i].b);
work(m1, 1);
work(m2, 2);
for(int i = 1; i < n; i++)
for(int j = 1; j < 3; j++)
f[j][i + 1] += f[j][i];
for(int i = 0; i <= n; i++)
{
int sum = f[1][i] + f[2][n - i];
ans = max(ans, sum);
}
printf("%d", ans);
return 0;
}
愿自己不再辜负自己,奇迹不再辜负奇迹。