1. 程式人生 > 其它 >CSP2021S2T1 廊橋分配 題解

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;
}