結果
| 問題 |
No.3327 うるせぇ、ポリオミノぶつけんぞ
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-11-05 16:49:27 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 6,000 bytes |
| コンパイル時間 | 361 ms |
| コンパイル使用メモリ | 82,604 KB |
| 実行使用メモリ | 211,464 KB |
| 最終ジャッジ日時 | 2025-11-05 16:49:34 |
| 合計ジャッジ時間 | 6,522 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 7 TLE * 1 -- * 16 |
ソースコード
import bisect
INF = 10**18
# 定数 INF は既存のまま使ってください
class LazySegTree:
"""
高速化版:
- (val,idx) を分離して保持
- nested function 廃止
- lambda/min,max 呼び出しを直接比較に置換
"""
def __init__(self, n):
self.N = n
self.size = 1
while self.size < n:
self.size <<= 1
m = 2 * self.size
# 値とインデックスを分離して保持
self.minv = [INF] * m
self.minidx = [-1] * m
self.maxv = [-INF] * m
self.maxidx = [-1] * m
self.lazy = [0] * m
# 葉の index をセット
for i in range(n):
pos = i + 1
self.minv[self.size + i] = INF
self.minidx[self.size + i] = pos
self.maxv[self.size + i] = -INF
self.maxidx[self.size + i] = pos
for i in range(self.size - 1, 0, -1):
self._pull(i)
def _pull(self, idx):
L = idx * 2
R = L + 1
# min
if self.minv[L] <= self.minv[R]:
self.minv[idx] = self.minv[L]
self.minidx[idx] = self.minidx[L]
else:
self.minv[idx] = self.minv[R]
self.minidx[idx] = self.minidx[R]
# max
if self.maxv[L] >= self.maxv[R]:
self.maxv[idx] = self.maxv[L]
self.maxidx[idx] = self.maxidx[L]
else:
self.maxv[idx] = self.maxv[R]
self.maxidx[idx] = self.maxidx[R]
def _apply(self, idx, val):
# 直接更新(タプル生成なし)
self.minv[idx] += val
self.maxv[idx] += val
if idx < self.size:
self.lazy[idx] += val
def _push(self, idx):
v = self.lazy[idx]
if v != 0:
L = idx * 2
R = L + 1
# 子に直接足す(分岐少)
self.minv[L] += v
self.maxv[L] += v
self.minv[R] += v
self.maxv[R] += v
if L < self.size:
self.lazy[L] += v
if R < self.size:
self.lazy[R] += v
self.lazy[idx] = 0
# 区間加算
def range_add(self, l, r, val):
self._range_add(1, 1, self.size, l, r, val)
def _range_add(self, idx, nl, nr, l, r, val):
if r < nl or nr < l:
return
if l <= nl and nr <= r:
self._apply(idx, val)
return
self._push(idx)
mid = (nl + nr) // 2
self._range_add(idx * 2, nl, mid, l, r, val)
self._range_add(idx * 2 + 1, mid + 1, nr, l, r, val)
self._pull(idx)
# 区間最小
def range_min(self, l, r):
return self._range_min(1, 1, self.size, l, r)
def _range_min(self, idx, nl, nr, l, r):
if r < nl or nr < l:
return (INF, -1)
if l <= nl and nr <= r:
return (self.minv[idx], self.minidx[idx])
self._push(idx)
mid = (nl + nr) // 2
left = self._range_min(idx * 2, nl, mid, l, r)
right = self._range_min(idx * 2 + 1, mid + 1, nr, l, r)
# 直接比較(タプル比較ではなく値比較)
if left[0] <= right[0]:
return left
else:
return right
# 区間最大
def range_max(self, l, r):
return self._range_max(1, 1, self.size, l, r)
def _range_max(self, idx, nl, nr, l, r):
if r < nl or nr < l:
return (-INF, -1)
if l <= nl and nr <= r:
return (self.maxv[idx], self.maxidx[idx])
self._push(idx)
mid = (nl + nr) // 2
left = self._range_max(idx * 2, nl, mid, l, r)
right = self._range_max(idx * 2 + 1, mid + 1, nr, l, r)
if left[0] >= right[0]:
return left
else:
return right
# 1点更新
def point_set(self, pos, val):
self._point_set(1, 1, self.size, pos, val)
def _point_set(self, idx, nl, nr, pos, val):
if nl == nr:
self.minv[idx] = val
self.maxv[idx] = val
self.minidx[idx] = pos
self.maxidx[idx] = pos
self.lazy[idx] = 0
return
self._push(idx)
mid = (nl + nr) // 2
if pos <= mid:
self._point_set(idx * 2, nl, mid, pos, val)
else:
self._point_set(idx * 2 + 1, mid + 1, nr, pos, val)
self._pull(idx)
# 1点取得
def point_get(self, pos):
return self._point_get(1, 1, self.size, pos)
def _point_get(self, idx, nl, nr, pos):
if nl == nr:
return self.minv[idx]
self._push(idx)
mid = (nl + nr) // 2
if pos <= mid:
return self._point_get(idx * 2, nl, mid, pos)
else:
return self._point_get(idx * 2 + 1, mid + 1, nr, pos)
N, Q = (int(x) for x in input().split())
A=list(map(int, input().split()))
mem=[]
segm = LazySegTree(N)
segM = LazySegTree(N)
for num, i in enumerate(A, start = 1):
mem.append([i, num])
mem=sorted(mem, key=lambda x: x[0])
L=[]
for num, i in enumerate(mem, start = 1):
segm.point_set(num, i[1])
segM.point_set(num, i[1])
L.append([i[0], num])
ans=[]
for i in range(Q):
c, X = (int(x) for x in input().split())
idx = bisect.bisect_left(L, [X+1, -100])
if idx == len(L):
ans.append(-1)
continue
if c == 1:
num, sidx = L[idx]
res, seg_idx = segm.range_min(sidx, N)
if res == -1 or res == 1000000000:
ans.append(-1)
else:
ans.append(res)
segm.point_set(seg_idx, 1000000000)
segM.point_set(seg_idx, -1)
else:
num, sidx = L[idx]
res, seg_idx = segM.range_max(sidx, N)
if res == -1 or res == 1000000000:
ans.append(-1)
else:
ans.append(res)
segm.point_set(seg_idx, 1000000000)
segM.point_set(seg_idx, -1)
for i in ans:
print(i)