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.
The answer is tiny: at most . So precompute need[k] = minimum operations needed to make the OR have at least set bits, then answer queries with upper_bound.
Work with the current array, not just the original OR. Increments can destroy lower bits, so the state after each chosen operation matters.
If bit is currently missing from the OR, every element has bit . For element , the cheapest way to make bit become costs .
Triggering bit sets that bit but makes the lower bits of the chosen element zero. So after setting a missing bit, some lower OR bits may need repair.
To gain one OR bit, take the lowest currently missing bit , trigger it, then scan downward from to and re-trigger any lower bit that disappeared. Repeat until all bits are present.
Only bits matter, because every final value is at most . So the maximum answer is .
That means we can precompute the minimum cost for every possible answer:
Then each query budget asks for the largest with .
Triggering a missing bit
Suppose bit is currently absent from the OR. Then every array element has bit .
For one element , the cheapest increment that makes bit equal to is:
So we choose the element with maximum . That is the closest element to the next number with bit set.
After this increment, the chosen element has bit , but its lower bits become zero. That is the annoying part. Carries do not ask permission.
Repairing lower bits
If we trigger a higher bit, we might destroy lower bits that were previously contributing to the OR.
Example with one element:
We gained bit , but lost bit , so the OR popcount did not increase.
Therefore, when we add a new bit , we must repair any lower bits that disappeared. The right order is from high to low: . If bit is missing, trigger it greedily using the formula above.
This order matters. If you repair low bits first, a later higher trigger can wipe them out again. That would be impressively pointless.
Why choose the lowest missing bit?
Let be the lowest bit missing from the current OR. All bits below are currently present.
To increase the OR popcount by one, some missing bit must be created. Choosing a higher missing bit cannot be better: it costs no less structurally and can damage a larger lower range. Triggering the lowest missing bit creates the smallest possible repair job.
So one optimal growth step is:
After this, bit is present, all lower bits are present again, and higher bits were never changed. So the OR popcount increases by exactly .
Precomputation
Start with the original array as cur.
Let
For every , need[k]=0.
For each target answer from to :
need[target] = need[target - 1];bit = p down to 0:
a[i] mod 2^bit;Then answer each query using upper_bound(need.begin(), need.end(), b).
Complexity
There are only bits. For each target answer, we scan at most bits, and each trigger scans all elements.
So preprocessing costs:
and each query costs:
Memory is .
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
static ll get_or(const vector<ll>& a) {
ll res = 0;
for (ll x : a) res |= x;
return res;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n, q;
cin >> n >> q;
vector<ll> a(n);
for (ll &x : a) cin >> x;
vector<ll> need(32, 0);
int have = __builtin_popcountll(get_or(a));
for (int target = have + 1; target <= 31; target++) {
need[target] = need[target - 1];
ll cur_or = get_or(a);
int p = 0;
while ((cur_or >> p) & 1LL) p++;
for (int bit = p; bit >= 0; bit--) {
cur_or = get_or(a);
if ((cur_or >> bit) & 1LL) continue;
int best = 0;
ll mask = (1LL << bit) - 1;
for (int i = 1; i < n; i++) {
if ((a[i] & mask) > (a[best] & mask)) best = i;
}
ll add = (1LL << bit) - (a[best] & mask);
a[best] += add;
need[target] += add;
}
}
while (q--) {
ll b;
cin >> b;
int ans = int(upper_bound(need.begin(), need.end(), b) - need.begin()) - 1;
cout << ans << '\n';
}
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
static ll get_or(const vector<ll>& a) {
ll res = 0;
for (ll x : a) res |= x;
return res;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n, q;
cin >> n >> q;
vector<ll> a(n);
for (ll &x : a) cin >> x;
vector<ll> need(32, 0);
int have = __builtin_popcountll(get_or(a));
for (int target = have + 1; target <= 31; target++) {
need[target] = need[target - 1];
ll cur_or = get_or(a);
int p = 0;
while ((cur_or >> p) & 1LL) p++;
for (int bit = p; bit >= 0; bit--) {
cur_or = get_or(a);
if ((cur_or >> bit) & 1LL) continue;
int best = 0;
ll mask = (1LL << bit) - 1;
for (int i = 1; i < n; i++) {
if ((a[i] & mask) > (a[best] & mask)) best = i;
}
ll add = (1LL << bit) - (a[best] & mask);
a[best] += add;
need[target] += add;
}
}
while (q--) {
ll b;
cin >> b;
int ans = int(upper_bound(need.begin(), need.end(), b) - need.begin()) - 1;
cout << ans << '\n';
}
}
return 0;
}