CSP2021S2T1 廊桥分配 题解


题目传送门

题目大意

一个机场里面有 \(n\) 个廊桥,有 \(m1\) 架国内航班和 \(m2\) 架国际航班。每一架航班都有到达和离开的时间,保证所有飞机到达和离开的时间互不相同。
现在你需要把廊桥分成两部分,一部分只允许国际航班停靠,剩下的只允许国内航班停靠。机场的廊桥实行先到先得的规则,如果没有廊桥停靠就会停靠在远机位。
现在请问怎么分配廊桥能使能停在廊桥的飞机数量最多,现在要求这个最大值是多少。
\(n\le 10^5,1\le m1+m2 \le 10^5.\)

题目解析

首先先讲一下我的错解。。。
显然我们发现,随着分给国内机场的廊桥的改变,能停靠在廊桥的航班也会改变,并且是一个单峰函数,直接三分即可。
但是显然我们发现 CCF 给的大样例就不满足是单峰函数,所以这是错的。

我们可以假设有国内航班和国外航班无数个位置,编号为 \(1,2,\dots n\),如果飞机尽量往编号小的地方停靠,那么无论选择前面的编号作为廊桥都是最优的,我们可以预处理出这个值,然后枚举分给国内航班的廊桥就可以了。
预处理的时候可以用平衡树来优化。
算法复杂度 \(\Theta\left(n\log n\right)\)

代码:

#include<set>
#include<cstdio>
#include<algorithm>
#define db double
#define U unsigned
#define ll long long
#define lb long double
#define ull unsigned long long
#define Me(a,b) memset(a,b,sizeof(a))
template<typename _T> _T abs(_T a){ return a>0?a:-a; }
template<typename _T> _T max(_T a,_T b){ return a>b?a:b; }
template<typename _T> _T min(_T a,_T b){ return a<b?a:b; }
template<typename _T> void print(_T x){ if(x<0) putchar('-'),x=-x;
	if(x>9) print(x/10); putchar(x%10+48); return; }
#define EPS (1e-7)
#define INF (0x7fffffff)
#define LLINF (0x7fffffffffffffff)
#define maxn 100039
#define maxm
#define MOD
using namespace std;
#define Type int
Type read(){
	char c=getchar(); Type sum=0; int flag=0;
	while((c<'0'||c>'9')&&c!='-') c=getchar(); if(c=='-') c=getchar(),flag=1;
	while('0'<=c&&c<='9'){ sum=(sum<<1)+(sum<<3)+(c^48); c=getchar(); }
	if(flag) return -sum; return sum;
}
int n,m1,m2,f1[maxn],f2[maxn];
struct Plane{
	int st,en,num;
	bool operator < (const Plane x) const{ return this->st < x.st; }
}a1[maxn],a2[maxn];
int cmp(Plane x,Plane y){ return x.st<y.st; }
set<Plane> s; int flag[maxn];
void init(Plane a[],int f[],int m){
	s.clear(); int i,now=0; Plane tmp; set<Plane>::iterator it; for(i=1;i<=m;i++) s.insert(a[i]);
	while(!s.empty()){
		tmp=*s.begin(); s.erase(s.begin()); now++; f[now]=1;
		while(1){
			tmp.st=tmp.en; it=s.upper_bound(tmp);
			if(it==s.end()) break; f[now]++; s.erase(it); tmp=*it;
		}
	} return;
}
int maxx;
int main(){
	//freopen("airport.in","r",stdin);
	//freopen(".out","w",stdout);
	n=read(); m1=read(); m2=read(); int i;
	for(i=1;i<=m1;i++) a1[i].st=read(),a1[i].en=read(),a1[i].num=i; init(a1,f1,m1);
	for(i=1;i<=m2;i++) a2[i].st=read(),a2[i].en=read(),a2[i].num=i; init(a2,f2,m2);
	//for(i=1;i<=m1;i++) print(f1[i]),putchar(' '); putchar('\n');
	//for(i=1;i<=m1;i++) print(f2[i]),putchar(' '); putchar('\n');
	for(i=1;i<=m1;i++) f1[i]+=f1[i-1]; for(i=1;i<=m2;i++) f2[i]+=f2[i-1];
	for(i=0;i<=n;i++) if(f1[i]+f2[n-i]>maxx) maxx=f1[i]+f2[n-i];
	print(maxx); return 0;
}
posted @ 2021-10-27 20:24  jiangtaizhe001  阅读(187)  评论(0编辑  收藏  举报