結果
| 問題 |
No.1095 Smallest Kadomatsu Subsequence
|
| コンテスト | |
| ユーザー |
lam6er
|
| 提出日時 | 2025-03-20 20:34:41 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 921 ms / 2,000 ms |
| コード長 | 3,759 bytes |
| コンパイル時間 | 164 ms |
| コンパイル使用メモリ | 82,372 KB |
| 実行使用メモリ | 170,392 KB |
| 最終ジャッジ日時 | 2025-03-20 20:36:31 |
| 合計ジャッジ時間 | 11,878 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 30 |
ソースコード
import sys
import bisect
inf = float('inf')
class SegmentTree:
def __init__(self, max_size):
self.N = 1
while self.N < max_size:
self.N <<= 1
self.size = self.N
self.tree = [inf] * (2 * self.N)
def update_point(self, pos, value):
pos += self.N
if self.tree[pos] > value:
self.tree[pos] = value
pos >>= 1
while pos >= 1:
new_val = min(self.tree[2*pos], self.tree[2*pos+1])
if self.tree[pos] == new_val:
break
self.tree[pos] = new_val
pos >>= 1
def query_range(self, l, r):
res = inf
l += self.N
r += self.N
while l <= r:
if l % 2 == 1:
res = min(res, self.tree[l])
l += 1
if r % 2 == 0:
res = min(res, self.tree[r])
r -= 1
l >>= 1
r >>= 1
return res
def main():
input = sys.stdin.read().split()
N = int(input[0])
A = list(map(int, input[1:N+1]))
sorted_A = sorted(A)
rank = {v:i for i, v in enumerate(sorted_A)}
r = [rank[a] for a in A]
max_rank = len(sorted_A) - 1
# Compute min_left_less and min_left_greater
left_st = SegmentTree(max_rank + 1)
min_left_less = [inf] * N
min_left_greater = [inf] * N
for j in range(N):
current_r = r[j]
# Query for min_left_less
if current_r > 0:
q_l = 0
q_r = current_r - 1
min_val = left_st.query_range(q_l, q_r)
else:
min_val = inf
min_left_less[j] = min_val
# Query for min_left_greater
if current_r + 1 <= max_rank:
q_l = current_r + 1
q_r = max_rank
min_val = left_st.query_range(q_l, q_r)
else:
min_val = inf
min_left_greater[j] = min_val
# Update left_st
left_st.update_point(current_r, A[j])
# Compute min_right_less and min_right_greater
right_st = SegmentTree(max_rank + 1)
min_right_less = [inf] * N
min_right_greater = [inf] * N
for j in range(N-1, -1, -1):
current_r = r[j]
# Query for min_right_less
if current_r > 0:
q_l = 0
q_r = current_r - 1
min_val = right_st.query_range(q_l, q_r)
else:
min_val = inf
min_right_less[j] = min_val
# Query for min_right_greater
if current_r + 1 <= max_rank:
q_l = current_r + 1
q_r = max_rank
min_val = right_st.query_range(q_l, q_r)
else:
min_val = inf
min_right_greater[j] = min_val
# Update right_st
right_st.update_point(current_r, A[j])
ans = inf
# Check each possible middle element j (i < j < k)
for j in range(1, N-1): # j ranges from 1 to N-2 inclusive
# Case 1: j is the max, so we need elements < A[j] on both sides
case1_sum = inf
left_less = min_left_less[j]
right_less = min_right_less[j]
if left_less != inf and right_less != inf:
case1_sum = left_less + A[j] + right_less
# Case 2: j is the min, so we need elements > A[j] on both sides
case2_sum = inf
left_greater = min_left_greater[j]
right_greater = min_right_greater[j]
if left_greater != inf and right_greater != inf:
case2_sum = left_greater + A[j] + right_greater
current_min = min(case1_sum, case2_sum)
if current_min < ans:
ans = current_min
print(ans if ans != inf else -1)
if __name__ == '__main__':
main()
lam6er