【HihoCoder - 1269】 优化延迟 (优先队列+二分优化)
題干:
小Ho編寫了一個處理數據包的程序。程序的輸入是一個包含N個數據包的序列。每個數據包根據其重要程度不同,具有不同的"延遲懲罰值"。序列中的第i個數據包的"延遲懲罰值"是Pi。如果N個數據包按照<Pi1, Pi2, ... PiN>的順序被處理,那么總延遲懲罰
SP=1*Pi1+2*Pi2+3*Pi3+...+N*PiN(其中i1, i2, ... iN是1, 2, 3, ... N的一個排列)。
小Ho的程序會依次處理每一個數據包,這時N個數據包的總延遲懲罰值SP為
1*P1+2*P2+3*P3+...+i*Pi+...+N*PN。 ?
小Hi希望可以降低總延遲懲罰值。他的做法是在小Ho的程序中增加一個大小為K的緩沖區。N個數據包在被處理前會依次進入緩沖區。當緩沖區滿的時候會將當前緩沖區內"延遲懲罰值"最大的數據包移出緩沖區并進行處理。直到沒有新的數據包進入緩沖區時,緩沖區內剩余的數據包會按照"延遲懲罰值"從大到小的順序被依次移出并進行處理。
例如,當數據包的"延遲懲罰值"依次是<5, 3, 1, 2, 4>,緩沖區大小K=2時,數據包被處理的順序是:<5, 3, 2, 4, 1>。這時SP=1*5+2*3+3*2+4*4+5*1=38。
現在給定輸入的數據包序列,以及一個總延遲懲罰閾值Q。小Hi想知道如果要SP<=Q,緩沖區的大小最小是多少?
輸入
Line 1: N Q
Line 2: P1?P2?... PN
對于50%的數據: 1 <= N <= 1000
對于100%的數據: 1 <= N <= 100000, 0 <= Pi?<= 1000, 1 <= Q <= 1013
輸出
輸出最小的正整數K值能滿足SP<=Q。如果沒有符合條件的K,輸出-1。
樣例輸入
5 38 5 3 1 2 4樣例輸出
2
解題報告:
對于緩沖區的描述我們一般就直接用優先隊列了 復雜度為O(N*logN)
對于這個題如果我們考慮直接去暴力枚舉緩沖區K的大小,然后在優先隊列去入隊出隊算出 SP值得話, 復雜度為O(N^2logN)N為10^5 復雜度還是很高;我們可以觀察考慮到我們枚舉K的大小時K為單調的,而且我們發現隨著K變大 SP的值在單調遞減,所以我們可以想到二分K的大小,復雜度降為O(N*logN*logN)。其實這題不用二分也貌似能過。
AC代碼:
#include<bits/stdc++.h>using namespace std; const int MAX = 100000 + 5; int a[MAX]; long long n; long long q; //緩沖區大小為k bool ok(int k) {priority_queue<int > pq;int cnt = 1;long long ans = 0;for(int i = 1; i<=n; i++) {if(pq.size() <k) pq.push(a[i]);else {ans += cnt*pq.top();cnt++;pq.pop();i--;}}while(!pq.empty() ) {ans +=cnt*pq.top();pq.pop();cnt++;} // printf("ans = %lld\n",ans);if(ans<=q) return 1;else return 0; } int main() {int flag = 0;cin>>n>>q;for(int i = 1; i<=n; i++) {scanf("%d",&a[i]);}int l = 1,r = n,mid; mid = (l+r)/2;while(l<r) {mid = (l+r)/2;if(ok(mid) ) r = mid,flag = 1;else l = mid + 1; }if(flag == 1 ) printf("%d\n",l) ;else printf("-1\n");return 0 ;}?
總結:兩個坑。第一l初始化成1,不能初始化成0!不然就RE了,大概因為輸入n為1的時候 ?剛開始進去的mid為0了?然后ok函數的k為0,,,肯定有RE啊。。第二看清數據范圍 Q的范圍是1e13,所以需要開longlong。
總結
以上是生活随笔為你收集整理的【HihoCoder - 1269】 优化延迟 (优先队列+二分优化)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: rsrcmtr.exe - rsrcmt
- 下一篇: 支付宝和理财通里面的互联网存款彻底下架了