日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CSP-S2021试题T1廊桥分配详讲

發布時間:2023/12/31 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CSP-S2021试题T1廊桥分配详讲 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

來遲了來遲了,忘寫了。
我們來看看這道卡了本蒟蒻3個小時的題。
傳送門luoguP7913廊橋分配
題目大意:分為了國內和國外兩部分,飛機來了要么停廊橋要么走,有空位一定停,且停最小的,要如何分配廊橋才能使停的飛機數最大。
首先我們要知道一個事實:

對于n架飛機,有無數個廊橋,其中的一架飛機k,能夠停在廊橋的要求是總的廊橋數大于等于從第一架來的飛機到它飛來時使它能停到廊橋的廊橋數。
換而言之,對于某一架飛機,使它能停靠的廊橋數與有多少個廊橋無關。
至于為什么,我們可以思考:
盡管有無數個廊橋,但是飛機是嚴格按照停靠在最小的廊橋上,只要能滿足前k架飛機能全部停廊橋數,那么其余的廊橋是沒有用上的。

得到這個事實我們可以得到:
可以就用給出的總廊橋數來模擬,對于每一個廊橋,可以統計出在這個廊橋有多少個飛機停,所以總飛機停靠個數就是1~k個廊橋上的飛機總和,這個只需要前綴和處理即可,最后枚舉分配給國內,國外的廊橋數,并加到一起,更新max即可。
我們應該如何模擬飛機離開和進入呢?
這里使用兩個優先隊列來分別維護最小編號的廊橋和所在哪個廊橋的飛機離開時間。
首先先按飛機來的時間進行排序,將編號最小的廊橋給它,刪除該廊橋,再將它的離開時間和該廊橋編號壓入另一小根堆中,并以離開時間為第一關鍵字來排序。
對于每一架來的飛機,比較它來的時間和堆中飛機離開時間,若離開時間小于了來的時間,那么就說明該飛機已經離開,刪除該飛機,并又將它所在的廊橋編號壓入堆中,循環直達堆頂飛機的離開時間大于了它來的時間。
然后就又重復操作,取出最小編號的廊橋,刪除,將該廊橋和它離開時間一同壓入堆中即可。
處理完后,我們得到每一廊橋停靠的飛機數量,那么統計前綴和即是有這么多個廊橋能停靠的飛機總數量。枚舉比較即可。
時間復雜度O(nlog2n)
代碼實現:

#include<bits/stdc++.h> using namespace std;const int N=1e5+5; int n,m1,m2; priority_queue<int>id;//最小廊橋編號 priority_queue<pair<int,int> >q;//飛機離開時間和它所在的廊橋編號 int cfa[N],cfb[N];//統計該廊橋有多少個飛機停 struct node {int l,r; }a[N];bool comp(node x,node y) {return x.l<y.l; }int main() {scanf("%d%d%d",&n,&m1,&m2);for(int i=1;i<=m1;i++) scanf("%d%d",&a[i].l,&a[i].r);sort(a+1,a+m1+1,comp);for(int i=1;i<=n;i++) id.push(-i);for(int i=1;i<=m1;i++){while(!q.empty() && -q.top().first<a[i].l)//飛機已經離開 {id.push(-q.top().second);q.pop();}if(!id.empty())//還有廊橋可以分配 {cfa[-id.top()]++;q.push(make_pair(-a[i].r,-id.top()));id.pop();}}for(int i=1;i<=n;i++) cfa[i]+=cfa[i-1];while(!id.empty()) id.pop();while(!q.empty()) q.pop();//初始化 for(int i=1;i<=m2;i++) scanf("%d%d",&a[i].l,&a[i].r);sort(a+1,a+m2+1,comp);for(int i=1;i<=n;i++) id.push(-i);for(int i=1;i<=m2;i++){while(!q.empty() && -q.top().first<a[i].l) {id.push(-q.top().second);q.pop();}if(!id.empty()){cfb[-id.top()]++;q.push(make_pair(-a[i].r,-id.top()));id.pop();}}for(int i=1;i<=n;i++) cfb[i]+=cfb[i-1];int ans=0;for(int i=0;i<=n;i++) ans=max(ans,cfa[i]+cfb[n-i]);//枚舉分配給國內國外多少時最大 cout<<ans;return 0; }

總結

以上是生活随笔為你收集整理的CSP-S2021试题T1廊桥分配详讲的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。