廊桥分配(airport)


作为一个退役两年的蒟蒻,来刷刷今年的复赛第一题,把我弄emo了
开始我理解错误了,我每次选择r最小的那个停机坪再更新它,这样能保证空闲时间是最少的,于是我用了线段树保存最小值,只能过25,我怀疑我线段树打错了
就改用树状数组,还是25。至此我还没想到我的方法不对,又改用优先队列,还是25....崩溃了,整整弄了我四个小时
我才开始考虑我的想法的漏洞,我这样的话无法保证只用k个(0<=k<=n)使得停的飞机数最大。
最后想到用set,每次满足一个停机坪,使得能在这个停机坪停的飞机都停在上面,每次模拟,用到lower——bound
复杂度nlog(n)

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=1e6+5;
int n,m1,m2,cnt;
pair<int,int>tmp;
set<pair<int,int> >a,b;
set<pair<int,int> >::iterator id;
int sum1[maxn],sum2[maxn];
int calc1(){
	int res=0,now=0;
	while(1){
		id=a.lower_bound(make_pair(now,now));
		if(id==a.end())break;
		res++;
		now=id->second;
		a.erase(id);
	}
	return res;
}
int calc2(){
	int res=0,now=0;
	while(1){
		id=b.lower_bound(make_pair(now,now));
		if(id==b.end())break;
		res++;
		now=id->second;
		b.erase(id);
	}
	return res;
}
int main(){
	for(int i=1;i<=m1;i++)cin>>tmp.first>>tmp.second,a.insert(tmp);
	for(int i=1;i<=m2;i++)cin>>tmp.first>>tmp.second,b.insert(tmp);
	for(int i=1;i<=n;i++)
	sum1[i]=sum1[i-1]+calc1();
	for(int i=1;i<=n;i++)
	sum2[i]=sum2[i-1]+calc2();
	int maxx=0;
	for(int i=0;i<=n;i++)
	if(maxx<sum1[i]+sum2[n-i])maxx=sum1[i]+sum2[n-i];
	cout<<maxx<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/wzxbeliever/p/15652342.html