結果
| 問題 |
No.3188 K-th Lexmin
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-06-15 15:44:22 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 1,320 ms / 3,500 ms |
| コード長 | 11,748 bytes |
| コンパイル時間 | 481 ms |
| コンパイル使用メモリ | 82,712 KB |
| 実行使用メモリ | 209,876 KB |
| 最終ジャッジ日時 | 2025-06-15 15:45:04 |
| 合計ジャッジ時間 | 38,836 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 47 |
ソースコード
import types
_atcoder_code = """
# Python port of AtCoder Library.
__version__ = '0.0.1'
"""
atcoder = types.ModuleType('atcoder')
exec(_atcoder_code, atcoder.__dict__)
_atcoder__bit_code = """
def _ceil_pow2(n: int) -> int:
x = 0
while (1 << x) < n:
x += 1
return x
def _bsf(n: int) -> int:
x = 0
while n % 2 == 0:
x += 1
n //= 2
return x
"""
atcoder._bit = types.ModuleType('atcoder._bit')
exec(_atcoder__bit_code, atcoder._bit.__dict__)
_atcoder_segtree_code = """
import typing
# import atcoder._bit
class SegTree:
def __init__(self,
op: typing.Callable[[typing.Any, typing.Any], typing.Any],
e: typing.Any,
v: typing.Union[int, typing.List[typing.Any]]) -> None:
self._op = op
self._e = e
if isinstance(v, int):
v = [e] * v
self._n = len(v)
self._log = atcoder._bit._ceil_pow2(self._n)
self._size = 1 << self._log
self._d = [e] * (2 * self._size)
for i in range(self._n):
self._d[self._size + i] = v[i]
for i in range(self._size - 1, 0, -1):
self._update(i)
def set(self, p: int, x: typing.Any) -> None:
assert 0 <= p < self._n
p += self._size
self._d[p] = x
for i in range(1, self._log + 1):
self._update(p >> i)
def get(self, p: int) -> typing.Any:
assert 0 <= p < self._n
return self._d[p + self._size]
def prod(self, left: int, right: int) -> typing.Any:
assert 0 <= left <= right <= self._n
sml = self._e
smr = self._e
left += self._size
right += self._size
while left < right:
if left & 1:
sml = self._op(sml, self._d[left])
left += 1
if right & 1:
right -= 1
smr = self._op(self._d[right], smr)
left >>= 1
right >>= 1
return self._op(sml, smr)
def all_prod(self) -> typing.Any:
return self._d[1]
def max_right(self, left: int,
f: typing.Callable[[typing.Any], bool]) -> int:
assert 0 <= left <= self._n
assert f(self._e)
if left == self._n:
return self._n
left += self._size
sm = self._e
first = True
while first or (left & -left) != left:
first = False
while left % 2 == 0:
left >>= 1
if not f(self._op(sm, self._d[left])):
while left < self._size:
left *= 2
if f(self._op(sm, self._d[left])):
sm = self._op(sm, self._d[left])
left += 1
return left - self._size
sm = self._op(sm, self._d[left])
left += 1
return self._n
def min_left(self, right: int,
f: typing.Callable[[typing.Any], bool]) -> int:
assert 0 <= right <= self._n
assert f(self._e)
if right == 0:
return 0
right += self._size
sm = self._e
first = True
while first or (right & -right) != right:
first = False
right -= 1
while right > 1 and right % 2:
right >>= 1
if not f(self._op(self._d[right], sm)):
while right < self._size:
right = 2 * right + 1
if f(self._op(self._d[right], sm)):
sm = self._op(self._d[right], sm)
right -= 1
return right + 1 - self._size
sm = self._op(self._d[right], sm)
return 0
def _update(self, k: int) -> None:
self._d[k] = self._op(self._d[2 * k], self._d[2 * k + 1])
"""
atcoder.segtree = types.ModuleType('atcoder.segtree')
atcoder.segtree.__dict__['atcoder'] = atcoder
atcoder.segtree.__dict__['atcoder._bit'] = atcoder._bit
exec(_atcoder_segtree_code, atcoder.segtree.__dict__)
SegTree = atcoder.segtree.SegTree
_atcoder_string_code = """
import functools
import typing
def _sa_naive(s: typing.List[int]) -> typing.List[int]:
sa = list(range(len(s)))
return sorted(sa, key=lambda i: s[i:])
def _sa_doubling(s: typing.List[int]) -> typing.List[int]:
n = len(s)
sa = list(range(n))
rnk = s.copy()
tmp = [0] * n
k = 1
while k < n:
def cmp(x: int, y: int) -> int:
if rnk[x] != rnk[y]:
return rnk[x] - rnk[y]
rx = rnk[x + k] if x + k < n else -1
ry = rnk[y + k] if y + k < n else -1
return rx - ry
sa.sort(key=functools.cmp_to_key(cmp))
tmp[sa[0]] = 0
for i in range(1, n):
tmp[sa[i]] = tmp[sa[i - 1]] + (1 if cmp(sa[i - 1], sa[i]) else 0)
tmp, rnk = rnk, tmp
k *= 2
return sa
def _sa_is(s: typing.List[int], upper: int) -> typing.List[int]:
threshold_naive = 10
threshold_doubling = 40
n = len(s)
if n == 0:
return []
if n == 1:
return [0]
if n == 2:
if s[0] < s[1]:
return [0, 1]
else:
return [1, 0]
if n < threshold_naive:
return _sa_naive(s)
if n < threshold_doubling:
return _sa_doubling(s)
sa = [0] * n
ls = [False] * n
for i in range(n - 2, -1, -1):
if s[i] == s[i + 1]:
ls[i] = ls[i + 1]
else:
ls[i] = s[i] < s[i + 1]
sum_l = [0] * (upper + 1)
sum_s = [0] * (upper + 1)
for i in range(n):
if not ls[i]:
sum_s[s[i]] += 1
else:
sum_l[s[i] + 1] += 1
for i in range(upper + 1):
sum_s[i] += sum_l[i]
if i < upper:
sum_l[i + 1] += sum_s[i]
def induce(lms: typing.List[int]) -> None:
nonlocal sa
sa = [-1] * n
buf = sum_s.copy()
for d in lms:
if d == n:
continue
sa[buf[s[d]]] = d
buf[s[d]] += 1
buf = sum_l.copy()
sa[buf[s[n - 1]]] = n - 1
buf[s[n - 1]] += 1
for i in range(n):
v = sa[i]
if v >= 1 and not ls[v - 1]:
sa[buf[s[v - 1]]] = v - 1
buf[s[v - 1]] += 1
buf = sum_l.copy()
for i in range(n - 1, -1, -1):
v = sa[i]
if v >= 1 and ls[v - 1]:
buf[s[v - 1] + 1] -= 1
sa[buf[s[v - 1] + 1]] = v - 1
lms_map = [-1] * (n + 1)
m = 0
for i in range(1, n):
if not ls[i - 1] and ls[i]:
lms_map[i] = m
m += 1
lms = []
for i in range(1, n):
if not ls[i - 1] and ls[i]:
lms.append(i)
induce(lms)
if m:
sorted_lms = []
for v in sa:
if lms_map[v] != -1:
sorted_lms.append(v)
rec_s = [0] * m
rec_upper = 0
rec_s[lms_map[sorted_lms[0]]] = 0
for i in range(1, m):
left = sorted_lms[i - 1]
right = sorted_lms[i]
if lms_map[left] + 1 < m:
end_l = lms[lms_map[left] + 1]
else:
end_l = n
if lms_map[right] + 1 < m:
end_r = lms[lms_map[right] + 1]
else:
end_r = n
same = True
if end_l - left != end_r - right:
same = False
else:
while left < end_l:
if s[left] != s[right]:
break
left += 1
right += 1
if left == n or s[left] != s[right]:
same = False
if not same:
rec_upper += 1
rec_s[lms_map[sorted_lms[i]]] = rec_upper
rec_sa = _sa_is(rec_s, rec_upper)
for i in range(m):
sorted_lms[i] = lms[rec_sa[i]]
induce(sorted_lms)
return sa
def suffix_array(s: typing.Union[str, typing.List[int]],
upper: typing.Optional[int] = None) -> typing.List[int]:
'''
SA-IS, linear-time suffix array construction
Reference:
G. Nong, S. Zhang, and W. H. Chan,
Two Efficient Algorithms for Linear Time Suffix Array Construction
'''
if isinstance(s, str):
return _sa_is([ord(c) for c in s], 255)
elif upper is None:
n = len(s)
idx = list(range(n))
def cmp(left: int, right: int) -> int:
return typing.cast(int, s[left]) - typing.cast(int, s[right])
idx.sort(key=functools.cmp_to_key(cmp))
s2 = [0] * n
now = 0
for i in range(n):
if i and s[idx[i - 1]] != s[idx[i]]:
now += 1
s2[idx[i]] = now
return _sa_is(s2, now)
else:
assert 0 <= upper
for d in s:
assert 0 <= d <= upper
return _sa_is(s, upper)
def lcp_array(s: typing.Union[str, typing.List[int]],
sa: typing.List[int]) -> typing.List[int]:
'''
Longest-Common-Prefix computation
Reference:
T. Kasai, G. Lee, H. Arimura, S. Arikawa, and K. Park,
Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its
Applications
'''
if isinstance(s, str):
s = [ord(c) for c in s]
n = len(s)
assert n >= 1
rnk = [0] * n
for i in range(n):
rnk[sa[i]] = i
lcp = [0] * (n - 1)
h = 0
for i in range(n):
if h > 0:
h -= 1
if rnk[i] == 0:
continue
j = sa[rnk[i] - 1]
while j + h < n and i + h < n:
if s[j + h] != s[i + h]:
break
h += 1
lcp[rnk[i] - 1] = h
return lcp
def z_algorithm(s: typing.Union[str, typing.List[int]]) -> typing.List[int]:
'''
Z algorithm
Reference:
D. Gusfield,
Algorithms on Strings, Trees, and Sequences: Computer Science and
Computational Biology
'''
if isinstance(s, str):
s = [ord(c) for c in s]
n = len(s)
if n == 0:
return []
z = [0] * n
j = 0
for i in range(1, n):
z[i] = 0 if j + z[j] <= i else min(j + z[j] - i, z[i - j])
while i + z[i] < n and s[z[i]] == s[i + z[i]]:
z[i] += 1
if j + z[j] < i + z[i]:
j = i
z[0] = n
return z
"""
atcoder.string = types.ModuleType('atcoder.string')
exec(_atcoder_string_code, atcoder.string.__dict__)
suffix_array = atcoder.string.suffix_array
lcp_array = atcoder.string.lcp_array
# from atcoder.segtree import SegTree
# from atcoder.string import suffix_array, lcp_array
n_sum = 0
def solve():
n, k = map(int, input().split())
a = list(map(int, input().split()))
global n_sum
assert 1 <= n <= 2 * 10 ** 5
assert 1 <= k <= n * (n + 1) // 2
assert len(a) == n
assert all(1 <= x <= n for x in a)
n_sum += n
assert n_sum <= 5 * 10 ** 5
sa = suffix_array(a, n)
lcp = lcp_array(a, sa)
lcp.append(0)
lcp_min = SegTree(min, n + 1, lcp)
len_sum = SegTree(int.__add__, 0, [n - i for i in sa])
ans = []
length = 0
pos = 0
while True:
next_pos = lcp_min.max_right(pos, lambda x: x >= length + 1) + 1
width = next_pos - pos
next_sum = len_sum.prod(pos, next_pos) - length * width
if next_sum < k:
k -= next_sum
pos = next_pos
continue
ans.append(a[sa[pos]+length])
length += 1
if k <= width:
break
k -= width
print(*ans)
t = int(input())
assert 1 <= t <= 10 ** 5
for _ in range(t):
solve()