|
| 1 | +# https://leetcode.com/problems/minimum-operations-to-make-array-elements-zero |
| 2 | +# Math + observation |
| 3 | +# The number of divisions by 4 it takes to get a number to zero is floor(log4(n)) + 1 |
| 4 | +# Observation: you will always be able to do 2 simultaneous operations unless the sum is odd |
| 5 | +# This is the case since the log4 representation goes up by at most 1 each time |
| 6 | + |
| 7 | +from itertools import accumulate |
| 8 | +from collections import Counter |
| 9 | + |
| 10 | +MN = 16 # log4(10^9) |
| 11 | +p4 = list(accumulate([0] + [3 * 4 ** i for i in range(MN)])) |
| 12 | +covers = [[p4[i] + 1, p4[i + 1]] for i in range(MN)] # range of floor values |
| 13 | + |
| 14 | + |
| 15 | +# print(covers) |
| 16 | + |
| 17 | +def minOperations(queries: list[list[int]]) -> int: |
| 18 | + def get_prefix_count(mx): |
| 19 | + freq = Counter() |
| 20 | + for i in range(MN): |
| 21 | + l, r = covers[i] |
| 22 | + if mx >= r: |
| 23 | + freq[i + 1] += r - l + 1 # fully covered |
| 24 | + else: |
| 25 | + freq[i + 1] += mx - l + 1 # partially covered |
| 26 | + break |
| 27 | + return freq |
| 28 | + |
| 29 | + def get_range_count(l, r): |
| 30 | + return get_prefix_count(r) - get_prefix_count(l - 1) |
| 31 | + |
| 32 | + ans = [] |
| 33 | + for l, r in queries: |
| 34 | + freq = get_range_count(l, r) |
| 35 | + # (number of operations) * (frequency), use ceil division |
| 36 | + ans.append((sum(k * v for k, v in freq.items()) + 1) // 2) |
| 37 | + |
| 38 | + # print(ans) |
| 39 | + return sum(ans) |
| 40 | + |
| 41 | + |
| 42 | +print(minOperations(queries=[[1, 2], [2, 4], [2, 6]])) # 1,2,4 |
| 43 | + |
| 44 | +# # code used to make observations |
| 45 | +# def count_moves(n): |
| 46 | +# c = 0 |
| 47 | +# while n > 0: |
| 48 | +# n = n // 4 |
| 49 | +# c += 1 |
| 50 | +# return c |
| 51 | +# |
| 52 | +# |
| 53 | +# res = [] |
| 54 | +# for i in range(1, 100): |
| 55 | +# from math import log, floor |
| 56 | +# |
| 57 | +# print(i, count_moves(i), floor(log(i, 4)) + 1) |
| 58 | +# res.append(count_moves(i)) |
| 59 | +# |
| 60 | +# from collections import Counter |
| 61 | +# |
| 62 | +# print(Counter(res)) # frequencies: [3, 12, 48, ..., 3*4^x] |
0 commit comments