Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Don’t simulate the whole bag list. If a bag is destroyed after seconds have already passed, its weight is .
A destruction is free exactly when . So each bag has a latest second when it can still be destroyed for free.
Paid destructions never need to happen before free destructions. Moving a free destruction earlier only helps it, and moving an already-paid bag later keeps it paid anyway.
Now the problem becomes: each free-able bag has a deadline , and you want to schedule as many unit-time jobs as possible at times before their deadlines.
Sort the deadlines increasingly. Keep free = 0; for each deadline , if free <= d, schedule that bag for free and increment free. The answer is .
The doubling looks annoying, but the key is that a bag’s cost only depends on when it is destroyed.
If bag is destroyed at second , meaning exactly doublings have already happened, its weight is
It is free iff
Remember the statement says you pay only when the weight is strictly greater than , so weight exactly is still free. Tiny detail, easy place to throw away a WA like a clown.
Turn each bag into a deadline
For every bag, compute the largest such that
That means this bag can be destroyed for free at any time .
If , then even destroying it immediately costs , so it has no free deadline and can be ignored when maximizing free destructions.
Since , we can compute by repeatedly doubling the weight while it stays at most . No floating-point logs needed. Floating point is overkill here and, frankly, a bad habit for integer boundary problems.
Why paid bags can go last
Suppose some schedule destroys a paid bag before a free bag.
Swap those two actions:
So the total cost does not increase.
By repeatedly doing this, there is always an optimal schedule where all free destructions happen first, and all paid destructions happen after. Nice. The garbage can wait.
So if we want bags to be free, we only need to schedule them into times
Each chosen bag must be placed no later than its deadline.
This is now a classic greedy scheduling problem
We have a bunch of unit-time jobs, each with a deadline . We want to schedule as many as possible.
The greedy is:
free be the number of free bags already scheduled.free <= d, schedule this bag at time free and increment free.Why does this work?
When processing deadlines in increasing order, the current bag is one of the most urgent remaining bags. If the next available free slot is free, then:
free <= d, the bag fits, so taking it is always good.free > d, then slots through are already filled. There is no earlier slot left for this bag, and replacing a previously chosen bag with this one does not increase the count. So skipping it loses nothing.At the end, free is the maximum number of bags we can destroy without paying.
Therefore:
Complexity
For each test case, we sort at most deadlines:
with , so this is comfortably tiny.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll c;
cin >> n >> c;
vector<int> deadlines;
for (int i = 0; i < n; i++) {
ll x;
cin >> x;
if (x > c) continue;
int d = 0;
while (x * 2 <= c) {
x *= 2;
d++;
}
deadlines.push_back(d);
}
sort(deadlines.begin(), deadlines.end());
int freeBags = 0;
for (int d : deadlines) {
if (freeBags <= d) {
freeBags++;
}
}
cout << n - freeBags << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll c;
cin >> n >> c;
vector<int> deadlines;
for (int i = 0; i < n; i++) {
ll x;
cin >> x;
if (x > c) continue;
int d = 0;
while (x * 2 <= c) {
x *= 2;
d++;
}
deadlines.push_back(d);
}
sort(deadlines.begin(), deadlines.end());
int freeBags = 0;
for (int d : deadlines) {
if (freeBags <= d) {
freeBags++;
}
}
cout << n - freeBags << '\n';
}
}