题目描述
当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位。乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折。然而,因为廊桥的数量有限,所以这样的愿望不总是能实现。
机场分为国内区和国际区,国内航班飞机只能停靠在国内区,国际航班飞机只能停靠在国际区。一部分廊桥属于国内区,其余的廊桥属于国际区。
L 市新建了一座机场,一共有 �n 个廊桥。该机场决定,廊桥的使用遵循“先到先得”的原则,即每架飞机抵达后,如果相应的区(国内/国际)还有空闲的廊桥,就停靠在廊桥,否则停靠在远机位(假设远机位的数量充足)。该机场只有一条跑道,因此不存在两架飞机同时抵达的情况。
现给定未来一段时间飞机的抵达、离开时刻,请你负责将 �n 个廊桥分配给国内区和国际区,使停靠廊桥的飞机数量最多。
输入格式
输入的第一行,包含三个正整数 �,�1,�2n,m1,m2,分别表示廊桥的个数、国内航班飞机的数量、国际航班飞机的数量。
接下来 �1m1 行,是国内航班的信息,第 �i 行包含两个正整数 �1,�,�1,�a1,i,b1,i,分别表示一架国内航班飞机的抵达、离开时刻。
接下来 �2m2 行,是国际航班的信息,第 �i 行包含两个正整数 �2,�,�2,�a2,i,b2,i,分别表示一架国际航班飞机的抵达、离开时刻。
每行的多个整数由空格分隔。
输出格式
输出一个正整数,表示能够停靠廊桥的飞机数量的最大值。
输入数据 1
3 5 4
1 5
3 8
6 10
9 14
13 18
2 11
4 15
7 17
12 16
Copy
输出数据 1
7
Copy
输入数据 2
2 4 6
20 30
40 50
21 22
41 42
1 19
2 18
3 4
5 6
7 8
9 10
Copy
输出数据 2
4
Copy
输入数据 3
见文件中的 airport3.in
Copy
输出数据 3
见文件中的 airport3.ans
Copy
提示
【样例解释 #1】
在图中,我们用抵达、离开时刻的数对来代表一架飞机,如 (1,5)(1,5) 表示时刻 11 抵达、时刻 55 离开的飞机;用 √√ 表示该飞机停靠在廊桥,用 ×× 表示该飞机停靠在远机位。
我们以表格中阴影部分的计算方式为例,说明该表的含义。在这一部分中,国际区有 22 个廊桥,44 架国际航班飞机依如下次序抵达:
- 首先 (2,11)(2,11) 在时刻 22 抵达,停靠在廊桥。
- 然后 (4,15)(4,15) 在时刻 44 抵达,停靠在另一个廊桥。
- 接着 (7,17)(7,17) 在时刻 77 抵达,这时前 22 架飞机都还没离开、都还占用着廊桥,而国际区只有 22 个廊桥,所以只能停靠远机位。
- 最后 (12,16)(12,16) 在时刻 1212 抵达,这时 (2,11)(2,11) 这架飞机已经离开,所以有 11 个空闲的廊桥,该飞机可以停靠在廊桥。
根据表格中的计算结果,当国内区分配 22 个廊桥、国际区分配 11 个廊桥时,停靠廊桥的飞机数量最多,一共 77 架。
【样例解释 #2】
当国内区分配 22 个廊桥、国际区分配 00 个廊桥时,停靠廊桥的飞机数量最多,一共 44 架,即所有的国内航班飞机都能停靠在廊桥。
需要注意的是,本题中廊桥的使用遵循“先到先得”的原则,如果国际区只有 11 个廊桥,那么将被飞机 (1,19)(1,19) 占用,而不会被 (3,4)(3,4)、(5,6)(5,6)、(7,8)(7,8)、(9,10)(9,10) 这 44 架飞机先后使用。
数据范围与约定
对于 20%20% 的数据,�≤100n≤100,�1+�2≤100m1+m2≤100。 对于 40%40% 的数据,�≤5000n≤5000,�1+�2≤5000m1+m2≤5000。 对于 100%100% 的数据,1≤�≤1051≤n≤105,�1,�2≥1m1,m2≥1,�1+�2≤105m1+m2≤105,所有 �1,�,�1,�,�2,�,�2,�a1,i,b1,i,a2,i,b2,i 为数值不超过 108108 的互不相同的正整数,且保证对于每个 �∈[1,�1]i∈[1,m1],都有 �1,�<�1,�a1,i<b1,i,以及对于每个 �∈[1,�2]i∈[1,m2],都有 �2,�<�2,�a2,i<b2,i。
CSP-S 2021 第一题
代码
淦
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w*=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
struct Brige{
int t,num;
friend bool operator < (const Brige &X,const Brige &Y ){
return X.t>Y.t; //小根
}
};
struct node{ int st,ed; }A[N],B[N];
struct Airport{ int a,b; }dp[N],sum[N];
int n,ans;
int x,y;
priority_queue<Brige> q;
priority_queue<int,vector<int>,greater<int> > id; //小根堆,储存目前空余编号
inline bool cmp(node a,node b) { return a.st<b.st; }
int main()
{
// freopen("airport.in","r",stdin);
// freopen("airport.out","w",stdout);
n=read(),x=read(),y=read();
for(register int i=1;i<=x;i++){
A[i].st=read(),A[i].ed=read();
}
for(register int i=1;i<=y;i++){
B[i].st=read(),B[i].ed=read();
}
sort(A+1,A+x+1,cmp),sort(B+1,B+y+1,cmp);
int cnt=0;
for(register int i=1;i<=x;i++){
while(q.size()){
Brige now=q.top();
if(now.t>A[i].st) break;
q.pop(); //空闲,弹出
id.push(now.num); //第num号桥空闲
}
if(id.size()){ //有桥空闲
int now=id.top(); id.pop();
dp[now].a++; //使用第now号桥飞机停泊量++
q.push((Brige){A[i].ed,now});
}
else{ //无桥空闲
cnt++; //新建立一个桥
dp[cnt].a++;
q.push((Brige){A[i].ed,cnt});
}
}
cnt=0;
while(!q.empty()) q.pop();
while(!id.empty()) id.pop();
for(register int i=1;i<=y;i++){
while(q.size()){
Brige now=q.top();
if(now.t>B[i].st) break;
q.pop(); //空闲,弹出
id.push(now.num); //第num号桥空闲
}
if(id.size()){ //有桥空闲
int now=id.top(); id.pop();
dp[now].b++; //使用第now号桥飞机停泊量++
q.push((Brige){B[i].ed,now});
}
else{ //无桥空闲
cnt++; //新建立一个桥
dp[cnt].b++;
q.push((Brige){B[i].ed,cnt});
}
}
for(register int i=1;i<=n;i++) sum[i].a=sum[i-1].a+dp[i].a;
for(register int i=1;i<=n;i++) sum[i].b=sum[i-1].b+dp[i].b;
for(register int i=0;i<=n;i++){
ans=max(ans,sum[i].a+sum[n-i].b);
}
printf("%d\n",ans);
return 0;
}