Advertisement
hoangreal

Count increasing subsequence length k

Nov 18th, 2024
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.25 KB | Source Code | 0 0
  1. def solution(nums, k):
  2.    
  3.     """
  4.    1)
  5.    
  6.    sol_startFrom(i | cur_len)
  7.    -> sol_startFrom(next_i | cur_len - 1) for all possible next_i
  8.    
  9.    2)  i: 0 -> len(nums) - 1
  10.        next_i | i: i + 1 -> len(nums) - 1
  11.        cur_len: k -> 1
  12.  
  13.    """
  14.    
  15.     sol_startFrom = [
  16.         [None for __ in range(len(nums))]
  17.         for _ in range(k)
  18.     ]
  19.     solve_correct(sol_startFrom, nums = nums, k = k)
  20.     final_ans = sum(
  21.         sol_startFrom[k - 1][dp_i]
  22.         for dp_i in range(0, len(sol_startFrom[0]))
  23.     )
  24.     return final_ans
  25. def solve_correct(sol_startFrom, *, nums, k):
  26.     for cur_len in range(1, k + 1, 1):
  27.         for i in range(len(nums) - 1, -1, -1):
  28.             dp_i = i; dp_cur_len = cur_len - 1
  29.            
  30.             ans = sol_startFrom[dp_cur_len][dp_i]
  31.             if ans is not None:
  32.                 continue            
  33.            
  34.             if i == len(nums) - 1:
  35.                 ans = 1 if (cur_len == 1) else 0
  36.             elif cur_len == 1:
  37.                 ans = 1  
  38.  
  39.             else:
  40.                 ans = 0
  41.                 for next_i in range(i + 1, len(nums)):
  42.                     dp_next_i = next_i
  43.    
  44.                     if not (nums[next_i] > nums[i]):
  45.                         continue
  46.                    
  47.                     ans += sol_startFrom[dp_cur_len - 1][dp_next_i]
  48.            
  49.             sol_startFrom[dp_cur_len][dp_i] = ans
  50.     return
  51.  
  52. class SegmentTree:
  53.     def __init__(self, func, default, arr=None):
  54.         """
  55.        Initialize the Segment Tree.
  56.        :time complexity: O(n), where n is the number of elements in `arr` (if provided).
  57.        """
  58.         self.func = func
  59.         self.default = default
  60.         self.n = 1
  61.         while self.n < (len(arr) if arr else 0):
  62.             self.n <<= 1  # Find the next power of two
  63.         self.size = 2 * self.n
  64.         self.tree = [self.default] * self.size
  65.         self.lazy = [0] * self.size  # Lazy propagation array
  66.  
  67.         if arr:
  68.             for i, value in enumerate(arr):
  69.                 self.tree[self.n + i] = value
  70.             for i in range(self.n - 1, 0, -1):
  71.                 self.tree[i] = self.func(
  72.                     self.tree[2 * i], self.tree[2 * i + 1]
  73.                 )
  74.  
  75.     def update_range(self, l, r, val):
  76.         """
  77.        Add 'val' to all elements in the range [l, r).
  78.        time complexity: O(log n), where n is the number of elements.
  79.        """
  80.         def _push(self):
  81.             """
  82.            Push the lazy updates to the children nodes.
  83.            :time complexity: O(1)
  84.            """
  85.             if self.lazy[node] != 0:
  86.                 self.tree[node] += self.lazy[node] * (node_right - node_left + 1)  # Update current node
  87.                 if node < self.n:  # If not a leaf node
  88.                     self.lazy[2 * node] += self.lazy[node]
  89.                     self.lazy[2 * node + 1] += self.lazy[node]
  90.                 self.lazy[node] = 0        
  91.        
  92.         def _update(node, node_left, node_right):
  93.             self._push(node, node_left, node_right)
  94.             if node_right <= l or r <= node_left:
  95.                 return
  96.             if l <= node_left and node_right <= r:
  97.                 self.lazy[node] += val
  98.                 self._push(node, node_left, node_right)
  99.                 return
  100.             mid = (node_left + node_right) // 2
  101.             _update(2 * node, node_left, mid)
  102.             _update(2 * node + 1, mid, node_right)
  103.             self.tree[node] = self.func(self.tree[2 * node], self.tree[2 * node + 1])
  104.  
  105.         _update(1, 0, self.n)
  106.  
  107.     def update_point(self, idx, value):
  108.         """
  109.        Update the value at a specific index and propagate the change.
  110.  
  111.        :param idx: 0-based index to update.
  112.        :param value: New value.
  113.        :time complexity: O(log n), where n is the number of elements.
  114.        """
  115.         if idx < 0 or idx >= self.n:
  116.             raise IndexError("Index out of bounds")
  117.         node = self.n + idx
  118.         self.tree[node] = value
  119.         while node > 1:
  120.             node //= 2
  121.             self.tree[node] = self.func(self.tree[2 * node], self.tree[2 * node + 1])
  122.  
  123.     def query_range(self, l, r):
  124.         """
  125.        Query the aggregated value in the range [l, r).
  126.  
  127.        :param l: Left index (inclusive, 0-based).
  128.        :param r: Right index (exclusive, 0-based).
  129.        :return: Aggregated result.
  130.        :time complexity: O(log n), where n is the number of elements.
  131.        """
  132.         if l < 0 or r > self.n or l > r:
  133.             raise IndexError("Invalid query range")
  134.         res = self.default
  135.         l += self.n
  136.         r += self.n
  137.         while l < r:
  138.             if l % 2:
  139.                 res = self.func(res, self.tree[l] + self.lazy[l])
  140.                 l += 1
  141.             if r % 2:
  142.                 r -= 1
  143.                 res = self.func(res, self.tree[r] + self.lazy[r])
  144.             l //= 2
  145.             r //= 2
  146.         return res
  147.        
  148.  
  149. def count_increasing_subsequence(nums, k):
  150.     sol_startFrom = [
  151.         [None for __ in range(len(nums))]
  152.         for _ in range(k)
  153.     ]
  154.     solve(sol_startFrom, nums = nums, k = k)
  155.     final_ans = sum(
  156.         sol_startFrom[k - 1][dp_i]
  157.         for dp_i in range(0, len(sol_startFrom[0]))
  158.     )
  159.     return final_ans
  160. def solve(sol_startFrom, *, nums, k):
  161.     for cur_len in range(1, k + 1, 1):
  162.         for i in range(len(nums) - 1, -1, -1):
  163.             dp_i = i; dp_cur_len = cur_len - 1
  164.            
  165.             ans = sol_startFrom[dp_cur_len][dp_i]
  166.             if ans is not None:
  167.                 continue            
  168.            
  169.             if i == len(nums) - 1:
  170.                 ans = 1 if (cur_len == 1) else 0
  171.             elif cur_len == 1:
  172.                 ans = 1  
  173.  
  174.             else:
  175.                 ans = 0
  176.                 for next_i in range(i + 1, len(nums)):
  177.                     dp_next_i = next_i
  178.    
  179.                     if not (nums[next_i] > nums[i]):
  180.                         continue
  181.                    
  182.                     ans += sol_startFrom[dp_cur_len - 1][dp_next_i]
  183.            
  184.             sol_startFrom[dp_cur_len][dp_i] = ans
  185.     return
  186.  
  187. print(count_increasing_subsequence([2, 6, 4, 5, 7], 3)) # 5
  188. print(count_increasing_subsequence([12, 8, 11, 13, 10, 15, 14, 16, 20], 4)) # 39
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement