Approach
Sorting and greedy selection
For ABC260 D — Draw Your Cards, the implementation first exposes a useful order, then scans that order while making locally justified choices.
- Choose the key that reveals the greedy or grouping structure.
- Sort the relevant records by that key.
- Scan in order, maintaining the invariant that makes each local choice safe.
Code notes
- 212 lines of Python from the credited upstream file abc260_d.py.
- The implementation visibly relies on sequence storage, hash lookup, ordered lookup.
- No explicit loop blocks detected.
Complexity
Sorting is typically the dominant term unless the subsequent scan uses a more expensive nested operation.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
12 3 4import math5from bisect import bisect_left, bisect_right6from typing import Generic, Iterable, Iterator, TypeVar, Union, List7T = TypeVar('T')8 9 10class SortedSet(Generic[T]):11 """Sorted set (set) in C++.12 See:13 https:qiita.com/tatyam/items/492c70ac4c955c05560214 https:github.com/tatyam-prime/SortedSet/blob/main/SortedSet.py15 """16 17 BUCKET_RATIO = 5018 REBUILD_RATIO = 17019 20 def _build(self, a=None) -> None:21 "Evenly divide `a` into buckets."22 if a is None:23 a = list(self)24 25 size = self.size = len(a)26 bucket_size = int(math.ceil(math.sqrt(size / self.BUCKET_RATIO)))27 self.a = [a[size * i bucket_size: size * (i + 1) bucket_size] for i in range(bucket_size)]28 29 def __init__(self, a: Iterable[T] = []) -> None:30 """Make a new SortedSet from iterable.31 / O(N) if sorted and unique / O(N log N)32 """33 a = list(a)34 35 if not all(a[i] < a[i + 1] for i in range(len(a) - 1)): 36 a = sorted(set(a)) 37 38 self._build(a)39 40 def __iter__(self) -> Iterator[T]:41 for i in self.a:42 for j in i:43 yield j 44 45 def __reversed__(self) -> Iterator[T]:46 for i in reversed(self.a):47 for j in reversed(i):48 yield j49 50 def __len__(self) -> int:51 return self.size52 53 def __repr__(self) -> str:54 return "SortedSet" + str(self.a)55 56 def __str__(self) -> str:57 s = str(list(self))58 return "{" + s[1: len(s) - 1] + "}"59 60 def _find_bucket(self, x: T) -> List[T]:61 "Find the bucket which should contain x. self must not be empty."62 for a in self.a:63 if x <= a[-1]: 64 return a65 return a66 67 def __contains__(self, x: T) -> bool:68 if self.size == 0:69 return False70 71 a = self._find_bucket(x)72 i = bisect_left(a, x) 73 74 return i != len(a) and a[i] == x75 76 def add(self, x: T) -> bool:77 "Add an element and return True if added. / O(√N)"78 if self.size == 0:79 self.a = [[x]]80 self.size = 181 return True82 83 a = self._find_bucket(x)84 i = bisect_left(a, x) 85 86 if i != len(a) and a[i] == x:87 return False88 89 a.insert(i, x)90 self.size += 191 92 if len(a) > len(self.a) * self.REBUILD_RATIO:93 self._build()94 95 return True96 97 def discard(self, x: T) -> bool:98 "Remove an element and return True if removed. / O(√N)"99 if self.size == 0:100 return False101 102 a = self._find_bucket(x)103 i = bisect_left(a, x) 104 105 if i == len(a) or a[i] != x:106 return False107 108 a.pop(i)109 self.size -= 1110 111 if len(a) == 0:112 self._build()113 return True114 115 def lt(self, x: T) -> Union[T, None]:116 "Find the largest element < x, or None if it doesn't exist."117 for a in reversed(self.a):118 if a[0] < x: 119 return a[bisect_left(a, x) - 1] 120 return None121 122 def le(self, x: T) -> Union[T, None]:123 "Find the largest element <= x, or None if it doesn't exist."124 for a in reversed(self.a):125 if a[0] <= x: 126 return a[bisect_right(a, x) - 1] 127 return None128 129 def gt(self, x: T) -> Union[T, None]:130 "Find the smallest element > x, or None if it doesn't exist."131 for a in self.a:132 if a[-1] > x: 133 return a[bisect_right(a, x)] 134 return None135 136 def ge(self, x: T) -> Union[T, None]:137 "Find the smallest element >= x, or None if it doesn't exist."138 for a in self.a:139 if a[-1] >= x: 140 return a[bisect_left(a, x)] 141 return None142 143 def __getitem__(self, x: int) -> T:144 "Return the x-th element, or IndexError if it doesn't exist."145 if x < 0:146 x += self.size147 if x < 0:148 raise IndexError149 150 for a in self.a:151 if x < len(a):152 return a[x] 153 154 x -= len(a)155 raise IndexError156 157 def index(self, x: T) -> int:158 "Count the number of elements < x."159 ans = 0160 161 for a in self.a:162 if a[-1] >= x: 163 return ans + bisect_left(a, x) 164 ans += len(a)165 return ans166 167 def index_right(self, x: T) -> int:168 "Count the number of elements <= x."169 ans = 0170 171 for a in self.a:172 if a[-1] > x: 173 return ans + bisect_right(a, x) 174 ans += len(a)175 return ans176 177 178def main():179 from collections import defaultdict180 import sys181 182 input = sys.stdin.readline183 184 n, k = map(int, input().split())185 p = list(map(int, input().split()))186 s = SortedSet()187 188 d = defaultdict(list)189 ans = [-1] * n190 191 for i, pi in enumerate(p, 1):192 x = s.gt(pi)193 194 if x is not None:195 d[pi] = d.pop(x)196 s.discard(x)197 198 d[pi].append(pi)199 s.add(pi)200 201 if len(d[pi]) == k:202 for di in d[pi]:203 ans[di - 1] = i204 205 s.discard(pi)206 207 print(*ans, sep="\n")208 209 210if __name__ == "__main__":211 main()212