AC

键盘敲碎夜深沉,代码如麻乱假真  •  3天前


/*
枚举国内和国际区的廊桥数量
有重复x->x+1加一个廊桥能多多少个飞机
当廊桥为x或x+1时,前x个廊桥已经是已经是最优的
故有空位时,优先安排最先的廊桥
*/
#include<bits/stdc++.h>
using namespace std;
int n,m1,m2;
struct pl{		//航班结构体
	int st;
	int en;
	bool operator < (pl b2) const {		//const表示该函数不会对变量造成影响
		return st < b2.st;		//按到达时间从小到大排序
	}
}a[100005],b[100005];
int ac[100005],bc[100005];		//预处理出有i个廊桥时,第i个廊桥的飞机数量
struct Bridge{
	int index;		//廊桥编号
	int endt;		//上一个飞机的结束时间
	bool operator < (Bridge b2) const {		//const表示该函数不会对变量造成影响
		return endt > b2.endt;
	}
};
int aused,bused;
priority_queue<Bridge> aw;		//已停飞机的廊桥(结束时间从大到小)
priority_queue<int ,vector<int>,greater<int>> ae;			//空着的廊桥
//同理,国际
priority_queue<Bridge> bw;		//已停飞机的廊桥
priority_queue<int ,vector<int>,greater<int>> be;			//空着的廊桥
int main(){
	cin>>n>>m1>>m2;
	for(int i=1;i<=m1;i++) cin>>a[i].st>>a[i].en;
	for(int i=1;i<=m2;i++) cin>>b[i].st>>b[i].en;
	sort(a+1,a+m1+1);
	sort(b+1,b+m2+1);	
	for(int i=1;i<=m1;i++){		//枚举飞机来
		while(!aw.empty()&&aw.top().endt<a[i].st){		//来时有空的廊桥
			ae.push(aw.top().index);
			aw.pop();
		}
		if(ae.empty()){		//没有空廊桥
			if(aused<n){
				aused++;		//直接建
				ac[aused]++;		//该廊桥新停了一架飞机
				aw.push({aused,a[i].en});		//加入已停廊桥队列
			}
			//已用的大于n,不管它
		}else{		//有空廊桥
			int x=ae.top();		//选最小编号的空廊桥
			ae.pop();
			ac[x]++;		//该廊桥多停了一架飞机
			aw.push({x,a[i].en});		//加入已停飞机廊桥队列
		}
	}
	//国际同理
	for(int i=1;i<=m2;i++){		//枚举飞机来
		while(!bw.empty()&&bw.top().endt<b[i].st){		//来时有空的廊桥
			be.push(bw.top().index);
			bw.pop();
		}
		if(be.empty()){		//没有空廊桥
			if(bused<n){
				bused++;		//直接建
				bc[bused]++;		//该廊桥新停了一架飞机
				bw.push({bused,b[i].en});		//加入已停廊桥队列
			}
			//已用的大于n,不管它
		}else{		//有空廊桥
			int x=be.top();		//选最小编号的空廊桥
			be.pop();
			bc[x]++;		//该廊桥多停了一架飞机
			bw.push({x,b[i].en});		//加入已停飞机廊桥队列
		}
	}
	//前面求出的是具体某个廊桥的最优解
	for(int i=1;i<=n;i++){
		ac[i]+=ac[i-1];
		bc[i]+=bc[i-1];		
	}		//前缀和处理之后,就是安排i个廊桥的最优飞机数
	int ans=-1;
	for(int i=0;i<=n;i++) ans=max(ans,ac[i]+bc[n-i]);	//枚举廊桥分配数
	cout<<ans<<"\n";
 	return 0;
}


评论:

请先登录,才能进行评论