題面
A B C D E F G H
難度:紅 橙 黃 綠 藍 紫 黑 黑
題解
A
題目大意:輸入 \(a\),\(b\),解不等式 \(b - 2x \le a - x (0 \le x \le a)\),輸出 \(a - x_{min}\)。
解題思路:移項,得 \(x \ge b - a\)。
#include <bits/stdc++.h>
using namespace std;
int t, a, b;
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d%d", &a, &b);
if (a >= b) printf("%d\n", a);
else {
int x = b - a;
if (x <= a) printf("%d\n", a - x);
else printf("0\n");
}
}
return 0;
}
B
洛谷上這道題的題意翻譯是我寫的。
題目大意:
本題有多組測試資料。
有一臺檸檬水自動售貨機。機器上有 \(n\) 個槽位和 \(n\) 個按鈕,每個槽位對應一個按鈕,但你並不知道每個按鈕對應的是哪個槽位。
當您按下第 \(i\) 個按鈕時,有兩種可能的事件:
- 若 \(i\) 號槽位有至少一瓶檸檬水,則其中一瓶檸檬水會從這個槽位裡掉下來,然後你會把它取走。
- 若 \(i\) 號槽位沒有檸檬水,則什麼都不會發生。
檸檬水下落速度很快,因此您看不清它從哪個槽位掉出。您只知道每個槽位中瓶裝檸檬水的數量 \(a_i(1 \le a_i \le 10^9)\)
您需要求出至少收到 \(k\) 瓶檸檬水的最小按按鈕次數。
資料保證機器中至少存在 \(k\) 瓶檸檬水。
題目分析:
貪心+排序。
定義“按鈕按空”表示:該按鈕按下若干次後,不再掉下檸檬水(即對應槽位中沒有檸檬水)。
設當前有檸檬水的槽位中,數量最少的槽位為 \(p\),顯然對於每個已知按下能掉出檸檬水的按鈕,至少需要按 \(a_p\) 次,才能使這些按鈕中存在“被按空”的按鈕。
因此考慮進行如下操作:找到所有有檸檬水的槽位中,數量最少的槽位的檸檬水數,設為 \(x\),然後對於所有“沒有被按空”的按鈕,每個分別按下 \(x\) 次。由於是最壞情況,下一個按鈕將“被按空”。此時標記這個按鈕,並在下一輪中不再按下它。
解題思路:
可以考慮從小到大對陣列 \(a\) 排序,再從小到大進行列舉,直到已經掉出的檸檬水數量達到 \(k\)。
總時間複雜度 \(O(n \text{log} n)\)。
注:寫下這篇題解時,作者想要練習一下堆的用法。
#include <bits/stdc++.h>
using namespace std;
long long n, k, a[200010];
priority_queue<long long, vector<long long>, greater<long long> > q;
int main() {
long long t;
scanf("%lld", &t);
while (t--) {
while (!q.empty()) q.pop();
scanf("%lld%lld", &n, &k);
for (long long i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
q.push(a[i]);
}
long long tmpn = n, cnt = 0;
long long ans = 0;
while (true) {
if ((q.top() - cnt) * tmpn >= k) {
ans += k;
break;
}
ans += (q.top() - cnt) * tmpn + 1;
k -= (q.top() - cnt) * tmpn;
tmpn--;
cnt = q.top();
q.pop();
}
printf("%lld\n", ans);
}
return 0;
}