LeetCode Entry

3495. Minimum Operations to Make Array Elements Zero

06.09.2025 hard 2025 kotlin rust

Sum query [a..b] of optimal pairwise /4 until range is zero

3495. Minimum Operations to Make Array Elements Zero hard blog post substack youtube

1.webp

Join me on Telegram

https://t.me/leetcode_daily_unstoppable/1104

Problem TLDR

Sum query [a..b] of optimal pairwise /4 until range is zero #hard #math

Intuition

Didn’t solve.

    //  2, 3, 4, 5, 6
    // nums are consequent,
    // there can be a fast way to check ops count

    //              *
    //           *  *
    //        *  *  * ------ divide by four
    //     *  *  *  *
    //  *  *  *  *  *
    //  *  *  *  *  *
    //  0  0  1  1  1

    //    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
    //    1 1 1 2 2 2 2 2 2 2  2  2  2  2  2  3 ....
    //  1*3+12*2 +
    //  1*(4^1-4^0) + 2*(4^2-4^1) + 3*(4^3-4^2)
    //
    // optimal way?
    // pairs  1 2 3 4 5
    //                  the largest log_4(X) steps
    //    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
    //      .       .                       3 4
    //      .       .                       0 1
    //      .       .                    3    0
    //      .       .                 3  0
    //      .       .              3  0
    //      .       .           2  0
    //      .       .        2  0
    //      .       .     2  0
    //      .       .   2 0
    //      .       . 1 0
    //      .       1 0
    //      .     1 0
    //      .   1 0
    //      . 0 0
    //    0 0

    //  1 1 1 1 2 2 2 2 2 2  2  2  2  2  2  2  3 3
    //      a                                    b

    //                                     4^3
    //                                     4^2
    //                                     4^1
    //                                     4^0
    //                                     0

    // we have this sequence
    //
    //  1*(4^1-4^0) + 2*(4^2-4^1) + 3*(4^3-4^2) + k*(4^k-4^(k-1))
    //       /                           \
    //      a                             b somewhere there
    //
    //    1 1 1 2 2 2 2 2 2  2  2  2  2  2  2  3 3
    //      a=3     .                           b=17
    //              .                          3..steps
    //              .                    2....steps
    //              .              2....steps
    //              .        2....steps
    //              .   2....steps
    //              2....steps
    //          2....steps
    //      1...step
    // r=1+2*6+3=1+2*(4^2-4^1)/2+3
    // how many steps to take pairs from a to b
    //
    // 1. find which range is b
    // ok let's look for hints (44 minute)
    // first hint already knew - steps(x) = log_4(x)
    // second hint don't understand - pair 2 numbers with max "/4" what?

  • each number has uniq growing number of ops
  • the sequence of ops is 1*(4^1-4^0) + 2*(4^2-4^1) + 3*(4^3-4^2) + k*(4^k-4^(k-1))
  • compute sum of individual ops in range: ops += (r-l+1)*pow
  • convert to pairwise and handle edge case of odd numbers: res += ops/2+ops%2

Approach

  • i was close to the solution, just didn’t believe i’m on a right track;
  • the tricky part is converting from singles to pairwise ops; have to do big observation for this, or just give up
  • not mine bithack: 0x15555555 >> (30 - 2*p)evaluates to 1 + 4 + 4² + … + 4^{p-1}. Why? 0x15555555 is the bit pattern 0101... (1s in even positions). Shifting by 30-2p moves exactly p of those 1s into the low end, giving the geometric series above.

Logic behind (x+1)*p-(4^p-1)/3: image.png

For [a,b]=[20,70]: 1.webp

Complexity

  • Time complexity: \(O(nlog(d))\)

  • Space complexity: \(O(1)\)

Code


// 8ms
    fun f(x: Int): Long = ((33 - x.countLeadingZeroBits()) shr 1).let { p ->
        1L*(x + 1) * p - (0x15555555 shr (30 - 2 * p)) }
    fun minOperations(qs: Array<IntArray>) = qs.sumOf { (f(it[1])-f(it[0]-1)+1)/2 }


// 69ms
    fun minOperations(qs: Array<IntArray>) =
        qs.sumOf { (a,b) ->
            ((1..16).sumOf { p ->
                max(0, 1L*min(b, (1 shl p*2)-1) - max(a, 1 shl (p-1)*2) + 1) * p
            }+1) / 2
        }


// 24ms
    pub fn min_operations(q: Vec<Vec<i32>>) -> i64 {
        q.iter().map(|q| (1+(1..17).map(|p|
            0.max(1 + q[1].min((1<<p*2)-1) - q[0].max(1<<(p-1)*2)) as i64*p
        ).sum::<i64>())/2 ).sum::<i64>()
    }


// 30ms
    long long minOperations(vector<vector<int>>& q) {
        long long r = 0, o = 1;
        for (auto& q: q) {
            for (int p = 1; p < 17; ++p)
            o += p * max(0LL, 1LL + min(1LL*q[1], (1LL<<p*2)-1) - max(1LL*q[0], 1LL<<(p-1)*2));
            r += o / 2, o = 1;
        }
        return r;
    }