3495: Minimum-Operations-to-Make-Array-Elements-Zero
Hard
table of contents
Not a bad question!
Since you are given a list of queries
, my first instinct
was to pre-compute 1e9
values but I was unfortunately hit
with a Memory Limit Exceeded
; I guess I have to settle for
logarithmic time-
My intuition for this question is that we can convert each number in a query into actions. For example:
- the number
4
would take2
actions as4 -> 1 -> 0
as - the number
1234
would take6
actions as1234 -> 308 -> 77 -> 19 -> 4 -> 1 -> 0
Then, using the newly converted array of actions, we
can sum up all the actions inside of any query to get a value;
let us call it sum
. Using sum
, we can
calculate the number of operations needed for every
query numberOfOperations = sum / 2 + sum % 2
(I tested this
out on several test-cases, but it is definitely proveable using
induction).
Now, going through the algorithm, we keep track of the minimum
operations using ans
and iterate through all the
queries
:
long long ans = 0;
for (vector<int>& query : queries) {
// more code incoming
}
We first define a function to get the number of actions needed for a given number:
int getActionCount(int number) {
int counter = 0;
for (; number > 0; number /= 4) {
++counter;
}
return counter;
}
Then, we keep track of the current sum of actions using
sum
and get the left and right action count for the bounds
of the query:
long long sum = 0;
int leftActionCount = getActionCount(query[0]);
int rightActionCount = getActionCount(query[1]);
Now, we iterate between the left and right bounds of the query in
chunks, where each chunk is separated based on the
number’s action count, to calculate the sum
value for the
query:
int currentIndex = query[0];
long long limit = pow(4, leftActionCount);
for (; leftActionCount <= rightActionCount; ++leftActionCount) {
+= (min(limit, (long long)query[1]+1)-currentIndex) * leftActionCount;
sum = limit;
currentIndex *= 4;
limit }
Finally, we use the equation above
numberOfOperations = sum / 2 + sum % 2
and add it to our
ans
:
+= sum / 2 + sum % 2; ans
code
class Solution {
public:
long long minOperations(vector<vector<int>>& queries) {
long long ans = 0;
for (vector<int>& query : queries) {
long long sum = 0;
int leftActionCount = getActionCount(query[0]);
int rightActionCount = getActionCount(query[1]);
int currentIndex = query[0];
long long limit = pow(4, leftActionCount);
for (; leftActionCount <= rightActionCount; ++leftActionCount) {
+= (min(limit, (long long)query[1]+1)-currentIndex) * leftActionCount;
sum = limit;
currentIndex *= 4;
limit }
+= sum / 2 + sum % 2;
ans }
return ans;
}
private:
int getActionCount(int number) {
int counter = 0;
for (; number > 0; number /= 4) {
++counter;
}
return counter;
}
};