廊桥分配

廊桥分配

国内国际是完全独立的,可以分开考虑。

发现如果每次我们让新来的航班强制使用当前编号最小的空闲廊桥,那么对于一个给定的 \(k\),停靠到编号 \(\ge k\) 的就是在只有 \(k\) 个廊桥时无法使用到廊桥的航班。所以我们可以直接先假设有 \(n\) 个廊桥做一遍,记录每个廊桥被使用的次数,做一个前缀和就是对于特定数量的廊桥可以使用廊桥的航班个数。具体而言,可以使用两个堆

  1. 表示已用的廊桥情况:结束时间,占用的廊桥编号

  2. 表示空闲的廊桥编号

每次都可以将可释放的廊桥放入 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;
}
posted @ 2023-05-21 19:44  wscqwq  阅读(79)  评论(0编辑  收藏  举报