結果
| 問題 |
No.3327 うるせぇ、ポリオミノぶつけんぞ
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-11-05 17:25:28 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 2,559 ms / 3,000 ms |
| コード長 | 4,297 bytes |
| コンパイル時間 | 358 ms |
| コンパイル使用メモリ | 82,704 KB |
| 実行使用メモリ | 179,336 KB |
| 最終ジャッジ日時 | 2025-11-05 17:26:04 |
| 合計ジャッジ時間 | 34,986 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge7 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 24 |
ソースコード
import bisect
INF = 10**18
class DualSegTree:
"""
1本で range_min / range_max 両対応。
無効化は None をセットすることで対応。
"""
def __init__(self, n):
self.N = n
size = 1
while size < n:
size <<= 1
self.size = size
self.minv = [INF] * (2 * size)
self.minidx = [0] * (2 * size)
self.maxv = [-INF] * (2 * size)
self.maxidx = [0] * (2 * size)
self.valid = [False] * (2 * size)
# 葉ノードにインデックス
for i in range(n):
leaf = size + i
self.minidx[leaf] = self.maxidx[leaf] = i + 1
# ---------------------------------
# 点更新(val=Noneで無効化)
# ---------------------------------
def point_set(self, pos, val):
p = self.size + (pos - 1)
if val is None:
self.minv[p] = INF
self.maxv[p] = -INF
self.valid[p] = False
else:
self.minv[p] = self.maxv[p] = val
self.valid[p] = True
# 再計算
p >>= 1
while p:
L = p * 2
R = L + 1
# merge
if not self.valid[L] and not self.valid[R]:
self.minv[p] = INF
self.maxv[p] = -INF
self.valid[p] = False
else:
self.valid[p] = self.valid[L] or self.valid[R]
# min
if self.minv[L] <= self.minv[R]:
self.minv[p] = self.minv[L]
self.minidx[p] = self.minidx[L]
else:
self.minv[p] = self.minv[R]
self.minidx[p] = self.minidx[R]
# max
if self.maxv[L] >= self.maxv[R]:
self.maxv[p] = self.maxv[L]
self.maxidx[p] = self.maxidx[L]
else:
self.maxv[p] = self.maxv[R]
self.maxidx[p] = self.maxidx[R]
p >>= 1
# ---------------------------------
# range_min
# ---------------------------------
def range_min(self, l, r):
l = l + self.size - 1
r = r + self.size - 1
best_val = INF
best_idx = -1
while l <= r:
if l & 1:
if self.valid[l] and self.minv[l] < best_val:
best_val = self.minv[l]
best_idx = self.minidx[l]
l += 1
if not (r & 1):
if self.valid[r] and self.minv[r] < best_val:
best_val = self.minv[r]
best_idx = self.minidx[r]
r -= 1
l >>= 1
r >>= 1
return (best_val, best_idx)
# ---------------------------------
# range_max
# ---------------------------------
def range_max(self, l, r):
l = l + self.size - 1
r = r + self.size - 1
best_val = -INF
best_idx = -1
while l <= r:
if l & 1:
if self.valid[l] and self.maxv[l] > best_val:
best_val = self.maxv[l]
best_idx = self.maxidx[l]
l += 1
if not (r & 1):
if self.valid[r] and self.maxv[r] > best_val:
best_val = self.maxv[r]
best_idx = self.maxidx[r]
r -= 1
l >>= 1
r >>= 1
return (best_val, best_idx)
N, Q = (int(x) for x in input().split())
A = list(map(int, input().split()))
mem = [[a, i+1] for i, a in enumerate(A)]
mem.sort(key=lambda x: x[0])
L = []
seg = DualSegTree(N)
for num, (val, idx) in enumerate(mem, start=1):
seg.point_set(num, idx)
L.append([val, num])
ans = []
for _ in range(Q):
c, X = map(int, input().split())
idx = bisect.bisect_left(L, [X+1, -INF])
if idx == len(L):
ans.append(-1)
continue
num, sidx = L[idx]
if c == 1:
val, seg_idx = seg.range_min(sidx, N)
else:
val, seg_idx = seg.range_max(sidx, N)
if val == INF or val == -INF or seg_idx == -1:
ans.append(-1)
else:
ans.append(val)
seg.point_set(seg_idx, None) # ← 無効化ここ!
print(*ans, sep="\n")