CSP2021S2T1 廊橋分配 題解
阿新 • • 發佈:2021-10-27
目錄
題目傳送門
題目傳送門
題目大意
一個機場裡面有 \(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; }