@@ -58,13 +58,71 @@ def mask(cnt, l):
58
58
return dp [- 1 ] if dp [- 1 ] != INF else - 1
59
59
60
60
61
+ # Time: O(n * m * (logn + logr)), r = max(nums)
62
+ # Space: O(n + logr)
63
+ import collections
64
+
65
+
66
+ # dp, sparse table
67
+ class Solution2 (object ):
68
+ def minimumValueSum (self , nums , andValues ):
69
+ """
70
+ :type nums: List[int]
71
+ :type andValues: List[int]
72
+ :rtype: int
73
+ """
74
+ INF = float ("inf" )
75
+ # RMQ - Sparse Table
76
+ # Template: https://github.com/kamyu104/GoogleCodeJam-Farewell-Rounds/blob/main/Round%20D/genetic_sequences2.py3
77
+ # Time: ctor: O(NlogN) * O(fn)
78
+ # query: O(fn)
79
+ # Space: O(NlogN)
80
+ class SparseTable (object ):
81
+ def __init__ (self , arr , fn ):
82
+ self .fn = fn
83
+ self .bit_length = [0 ]
84
+ n = len (arr )
85
+ k = n .bit_length ()- 1 # log2_floor(n)
86
+ for i in xrange (k + 1 ):
87
+ self .bit_length .extend (i + 1 for _ in xrange (min (1 << i , (n + 1 )- len (self .bit_length ))))
88
+ self .st = [[0 ]* n for _ in xrange (k + 1 )]
89
+ self .st [0 ] = arr [:]
90
+ for i in xrange (1 , k + 1 ): # Time: O(NlogN) * O(fn)
91
+ for j in xrange ((n - (1 << i ))+ 1 ):
92
+ self .st [i ][j ] = fn (self .st [i - 1 ][j ], self .st [i - 1 ][j + (1 << (i - 1 ))])
93
+
94
+ def query (self , L , R ): # Time: O(fn)
95
+ i = self .bit_length [R - L + 1 ]- 1
96
+ return self .fn (self .st [i ][L ], self .st [i ][R - (1 << i )+ 1 ])
97
+
98
+ dp = [INF ]* (len (nums )+ 1 )
99
+ dp [0 ] = 0
100
+ for j in xrange (len (andValues )):
101
+ new_dp = [INF ]* (len (nums )+ 1 )
102
+ masks = []
103
+ st = SparseTable (dp , min )
104
+ for i in xrange (j , len (nums )):
105
+ masks .append ([nums [i ], i ])
106
+ for x in masks :
107
+ x [0 ] &= nums [i ]
108
+ masks = [x for k , x in enumerate (masks ) if k == 0 or masks [k - 1 ][0 ] != masks [k ][0 ]]
109
+ for k , [mask , left ] in enumerate (masks ):
110
+ right = masks [k + 1 ][1 ]- 1 if k + 1 != len (masks ) else i
111
+ if mask == andValues [j ]:
112
+ # any j in range(left, right+1) have same and(nums[j:i+1]) = mask
113
+ new_dp [i + 1 ] = min (new_dp [i + 1 ], st .query (left , right )+ nums [i ])
114
+ break
115
+ dp = new_dp
116
+ return dp [- 1 ] if dp [- 1 ] != INF else - 1
117
+
118
+
61
119
# Time: O(n * m * logr), r = max(nums)
62
120
# Space: O(n * m * logr)
63
121
import collections
64
122
65
123
66
124
# memoization
67
- class Solution2 (object ):
125
+ class Solution3 (object ):
68
126
def minimumValueSum (self , nums , andValues ):
69
127
"""
70
128
:type nums: List[int]
0 commit comments