[CSP-S 2021] 廊桥分配

Problem

原题链接

Solution

首先我们考虑如果廊桥足够用我们应当怎样安排飞机,是不是每一次来一架飞机,我们就安排它到空闲的且编号最小的廊桥,这就可以保证廊桥使用率最高,这是可以用堆去搞的。
然后如果有了限制,我们假设远机位也是廊桥,那么就是按照上面分配方法来分,如果有 \(m\) 个廊桥,那么前 \(m\) 个位置就是真的廊桥,后面的位置就是假廊桥。概括地说,每个位置,无论它是廊桥还是远机位,它的飞机数目是不变的。比如,现在有 \(m\) 个廊桥,变成 \(m+1\) 个廊桥后,无非就是把第 \(m+1\) 个位置,由原来的远机位变成廊桥。
所以我们就按照第一段的分配方法去搞,预处理前缀和,然后枚举国内分几个廊桥就可以了。
还有这里要用小根堆,我的做法是开大根堆,每次丢它的相反数进去就可以了,取出来再还原。
时间复杂度:\(O(n \log n)\)

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
const int N=1e6+7;
struct node
{
	int l,r;
}a[N];
int s1[N],s2[N],n,m1,m2;
void init(int *s,int m)
{
	priority_queue<int>q;
	priority_queue<pair<int,int> >t;
	for(int i=1;i<=m;i++)q.push(-i);
	for(int i=1;i<=m;i++)
	{
		while(!t.empty()&&a[i].l>-t.top().first)
		{
			q.push(-t.top().second);
			t.pop();
		}
		int u=-q.top();q.pop();
		t.push(make_pair(-a[i].r,u));
		s[u]++;
	}
	for(int i=1;i<=n;i++)s[i]+=s[i-1];
}
bool cmp(node a,node b)
{return a.l<b.l;}
main()
{
	read(n);read(m1);read(m2);
	for(int i=1;i<=m1;i++)
		read(a[i].l),read(a[i].r);
	sort(a+1,a+m1+1,cmp);
	init(s1,m1);
	for(int i=1;i<=m2;i++)
		read(a[i].l),read(a[i].r);
	sort(a+1,a+m2+1,cmp);
	init(s2,m2);
	int ans=0;
	for(int i=0;i<=n;i++)
		ans=max(ans,s1[i]+s2[n-i]);
	cout<<ans;
	return 0;
}

后记

马上要打人生第一次提高了,VP 一下去年提高,其实还是有思维难度,越来越难了,这也说明人类在不断进化,现在普及模拟赛难度都可以出到省选了。。。
最后祝我自己 CSP-S2022 RP++!!!

posted @ 2022-07-28 23:24  Epoch_L  阅读(253)  评论(0编辑  收藏  举报