P7913 [CSP-S 2021] 廊桥分配

 

C++题目笔记——Luogu P7913

原题链接

此题也是课上的例题,属于杂题一类,主要思路就是通过模拟飞机停靠和飞机离开的操作找到最大值(答案),下面来总结一下容易犯的错误:

  1. 注意将s.insert(...)s.erase(...)t.insert(...)t.erase(...)等等这一类对set的操作写好,否则就会像我一样,死活根本就不输出任何东西(小注:t需要插入一个pair哦,你可以这样:t.insert({a,b});,也可以这样:t.insert(make_pair(a,b));
  2. 一定一定将a数组与b数组区分,否则又会像我一样,检查了好几遍才改对了(当然,这不算什么大问题,主要问题还是代码书写不认真)
  3. 在maxplane函数的最后记得对ans数组做前缀和操作,否则WA
  4. main函数中将国内飞机与国外飞机全部处理完后,下面的$for$循环应该从0开始,而不是从1开始,因为国内(或国外)廊桥数量可能为0。这在现实中是不会发生的。城市设计师们都很聪明,他们绝对不会做这种事情的哦!

附上AC代码(已补注释):

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
long long n,m1,m2,ans=-999999;
struct plane
{
	long long l,r;//l表示到达时间,r表示离开时间
}a[maxn],b[maxn];
bool cmp(plane x,plane y)
{
	return x.l<y.l;
}
vector<long long> maxplane(long long m1)
{
	for(int i=1;i<=m1;i++)
	{
		cin>>a[i].l>>a[i].r;
	}
	sort(a+1,a+1+m1,cmp);
	set<long long>s;//存储可用廊桥编号(1-n) 
	set<pair<long long,long long>>t;//存储飞机的离开时间&占用的廊桥编号 
	vector<long long>ans(1e5+1);//存储函数的结果 
	for(int i=1;i<=n;i++)
	{
		s.insert(i);
	}//初始化,往s中塞1-n,表示所有廊桥都可用 
	for(int i=1;i<=m1;i++)
	{
		//现在时间是a[i].l
		while(!t.empty()&&a[i].l>(*t.begin()).first)//(注:(*t.begin()).first指的是离开的时间)
		{
			//离开 
			s.insert((*t.begin()).second);//飞机离开,添加一个可用的廊桥(注:(*t.begin()).second指的是占用的廊桥编号)
			t.erase(t.begin());//将这个离开的飞机的到达时间&廊桥编号删除 
		}
		if(!s.empty())//如果还有廊桥可用 
		{
			//停靠 
			long long id=*s.begin();
			s.erase(id);//飞机到达,最小的廊桥被占,删除一个可用的廊桥 
			t.insert({a[i].r,id});//将到达时间&廊桥编号塞入t中
			ans[id]++;//飞机到达,停靠在编号最小的廊桥
		}	
	}
	for(int i=1;i<=n;i++)
	{
		ans[i]+=ans[i-1];
	}//对ans进行前缀和 
	return ans;
}
//说明:maxplane函数计算的是已知m1架飞机的l(到达时间),r(离开时间),计算每个廊桥最多能停靠多少架飞机(不考虑国内与国外)
int main()
{
	cin>>n>>m1>>m2;
	vector<long long>ans1=maxplane(m1);
	vector<long long>ans2=maxplane(m2);
  //分别对国内与国外进行一次maxplane处理
	for(int i=0;i<=n;i++)
	{
		ans=max(ans,ans1[i]+ans2[n-i]);//枚举所有情况(每次假设国内航班分配i个廊桥,国际航班分配n-i个廊桥)ans打擂台取最大值即可
	}
	cout<<ans<<endl;
} 

拒绝直接抄袭,共创美好世界。:smiley::smiley::smiley: