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.
Track . Every Poby move decreases by exactly .
Rekkles can increase only in one situation: he increments into . So the answer is initial plus the number of “useful” Rekkles moves.
Classify each live number as: type if it is , type if it is , and type otherwise.
A type element always contributes one useful Rekkles move eventually. Type contributes none. Type elements are weird: one alone contributes none, but every pair contributes one.
For a range, the value is Use prefix sums for those three quantities.
Let
This is the “division debt” of the current array.
If Poby changes into , then
So every Poby move decreases by exactly .
Rekkles changes into . This usually does not change . It increases it by only when
because then .
So if Rekkles makes useful moves, the final score is
The whole problem is now: how many useful Rekkles moves can happen under optimal play?
Classify each current element :
Let be the number of type elements and the number of type elements. The key claim is:
Yeah, that formula looks a little too clean. But it drops out nicely.
Define
We prove that is exactly the number of future useful Rekkles moves.
First look at Rekkles's move after Poby has moved.
If Rekkles touches a type element, two things can happen:
Either way, “immediate useful move plus new ” does not increase.
If Rekkles touches a type element, it becomes type . This increases exactly when the old was odd.
If Rekkles touches a type element, it either becomes type , or in the special case gives an immediate useful move. In both cases, the same parity rule appears: the combined value increases exactly when the old was odd.
So after Poby's move, Rekkles can add exactly
to the future useful-move count.
Now look at Poby.
If Poby divides a type element, then decreases by , so the parity flips. The decrease in and the parity bonus available to Rekkles perfectly cancel. Net result: stays the correct value.
If there is no type , then is even. Poby can divide any available element safely:
Again, net result is exactly the old .
So optimal play preserves the claim:
Therefore for the original query range :
Where inside the range:
Build prefix sums for:
Then each query is .
Complexity per test case:
Memory:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
static bool isPowerOfTwo(ll x) {
return x > 0 && (x & (x - 1)) == 0;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n, q;
cin >> n >> q;
vector<ll> prefLog(n + 1), prefType1(n + 1), prefType2(n + 1);
for (int i = 1; i <= n; i++) {
ll x;
cin >> x;
ll lg = 63 - __builtin_clzll(x);
bool type0 = isPowerOfTwo(x);
bool type1 = !type0 && isPowerOfTwo(x - 1);
bool type2 = !type0 && !type1;
prefLog[i] = prefLog[i - 1] + lg;
prefType1[i] = prefType1[i - 1] + type1;
prefType2[i] = prefType2[i - 1] + type2;
}
while (q--) {
int l, r;
cin >> l >> r;
ll sumLog = prefLog[r] - prefLog[l - 1];
ll cnt1 = prefType1[r] - prefType1[l - 1];
ll cnt2 = prefType2[r] - prefType2[l - 1];
cout << sumLog + cnt2 + cnt1 / 2 << '\n';
}
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
static bool isPowerOfTwo(ll x) {
return x > 0 && (x & (x - 1)) == 0;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n, q;
cin >> n >> q;
vector<ll> prefLog(n + 1), prefType1(n + 1), prefType2(n + 1);
for (int i = 1; i <= n; i++) {
ll x;
cin >> x;
ll lg = 63 - __builtin_clzll(x);
bool type0 = isPowerOfTwo(x);
bool type1 = !type0 && isPowerOfTwo(x - 1);
bool type2 = !type0 && !type1;
prefLog[i] = prefLog[i - 1] + lg;
prefType1[i] = prefType1[i - 1] + type1;
prefType2[i] = prefType2[i - 1] + type2;
}
while (q--) {
int l, r;
cin >> l >> r;
ll sumLog = prefLog[r] - prefLog[l - 1];
ll cnt1 = prefType1[r] - prefType1[l - 1];
ll cnt2 = prefType2[r] - prefType2[l - 1];
cout << sumLog + cnt2 + cnt1 / 2 << '\n';
}
}
}