Educational Codeforces Round 53 (Rated for Div. 2)D. Berland Fair(貪心)
阿新 • • 發佈:2018-11-01
題意
有 個物品圍成一圈,每個物品都有一個價值 ,現在有 元錢,現在從第一個物品開始順時針往後買,問在滿足下列條件下能買多少個物品。
- 如果當前剩餘的錢大於等於當前物品的價值,那就必須買下這個物品。
- 如果當前剩餘的錢不足以買下這個物品,則跳過。
- 如果當前的錢不足以買任何物品,則結束。
資料範圍
。
題解
因為T太大了,如果暴力迴圈購買肯定超時。超時的原因就是當一圈可以多次進行購買時,沒必要每個物品都迴圈過去。例如 , 5個物品價值為 ,那直接 即可。關鍵是如何得出當前的T和當前能買的價值總和。
用一個大根堆
儲存物品價值和
儲存當前價值總和。
如果
同時
,那麼肯定有一個物品的價值已經大於了當前剩餘的錢數,這個物品就可以丟掉不用考慮了。否則的話可能有兩種情況:
- 剩餘物品的單個價格都小於等於T,但是總和大於T。
- 剩餘物品的單個價格和總和都小於等於T。
對於情況1要遍歷全部物品,對於情況2直接加減乘除就好。
不斷重複上述步驟,直到物品總和為0。
大概為O(nlogT) 時間複雜度O(能過)。菜雞根本不會分析…
程式碼
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
const int maxn = 2e5+5;
typedef long long ll;
ll n,t,cnt,a[maxn];
int main() {
scanf("%lld%lld", &n,&t);
ll sum = 0;
ll total = n;
priority_queue<ll> que;
for(int i = 0; i < n; ++i) {
scanf("%lld", &a[i]);
que.push(a[i]);
sum += a[i];
}
while(1) {
while(sum > t && !que.empty() && que.top() > t) {
sum -= que.top();
que.pop();
total--;
}
if(sum == 0) break;
cnt += t/sum*total;
t %= sum;
for(int i = 0; i < n; ++i)
if(t >= a[i])
t -= a[i],cnt++;
}
printf("%lld\n", cnt);
return 0;
}