廊桥分配
廊桥分配
国内国际是完全独立的,可以分开考虑。
发现如果每次我们让新来的航班强制使用当前编号最小的空闲廊桥,那么对于一个给定的 \(k\),停靠到编号 \(\ge k\) 的就是在只有 \(k\) 个廊桥时无法使用到廊桥的航班。所以我们可以直接先假设有 \(n\) 个廊桥做一遍,记录每个廊桥被使用的次数,做一个前缀和就是对于特定数量的廊桥可以使用廊桥的航班个数。具体而言,可以使用两个堆
-
表示已用的廊桥情况:结束时间,占用的廊桥编号
-
表示空闲的廊桥编号
每次都可以将可释放的廊桥放入 2 堆,然后使用编号最小的廊桥,并加入 1 堆中。
注意
- 先将所有航班按照抵达时间排序,与题目中的先到先得原则对应。
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define Ls(i,l,r) for(int i=l;i<=r;++i)
#define Rs(i,l,r) for(int i=r;i>l;--i)
#define L(i,l) for(int i=0;i<l;++i)
typedef pair<int,int> pii;
const int N=100010;
int n,m1,m2,res1[N],res2[N];
pii a[N],b[N];
void calc(pii t[],int m,int res[]){
priority_queue<pii,vector<pii>,greater<pii> >lq;
priority_queue<int,vector<int>,greater<int> >wq;
Ls(i, 1, n)wq.push(i);
Ls(i, 1, m){
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();
++res[dest];
lq.push({t[i].y,dest});
}
Ls(i, 1, n)res[i]+=res[i-1];
}
int main(){
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
scanf("%d%d%d",&n,&m1,&m2);
Ls(i, 1, m1)scanf("%d%d",&a[i].x,&a[i].y);
Ls(i, 1, m2)scanf("%d%d",&b[i].x,&b[i].y);
sort(a+1,a+1+m1);
sort(b+1,b+1+m2);
calc(a,m1,res1);
calc(b,m2,res2);
int ans=0;
Ls(i, 0, n)ans=max(ans,res1[i]+res2[n-i]);
printf("%d",ans);
return 0;
}