結果

問題 No.3327 うるせぇ、ポリオミノぶつけんぞ
コンテスト
ユーザー urunea
提出日時 2025-11-05 16:46:27
言語 PyPy3
(7.3.15)
結果
TLE  
実行時間 -
コード長 5,388 bytes
コンパイル時間 309 ms
コンパイル使用メモリ 82,164 KB
実行使用メモリ 273,144 KB
最終ジャッジ日時 2025-11-05 16:46:34
合計ジャッジ時間 6,773 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1
other AC * 7 TLE * 1 -- * 16
権限があれば一括ダウンロードができます

ソースコード

diff #

import bisect

INF = 10**18

class LazySegTree:
    """
    1-indexedで使う範囲加算セグ木
    - range_add(l, r, val): 区間[l, r]にvalを加算
    - range_min(l, r): 区間[l, r]の(最小値, index)
    - range_max(l, r): 区間[l, r]の(最大値, index)
    - point_set(pos, val): 要素posをvalに変更
    - point_get(pos): 要素posの現在値を返す
    """

    def __init__(self, n):
        self.N = n
        self.size = 1
        while self.size < n:
            self.size <<= 1

        # 各ノードに (値, インデックス)
        self.minv = [(INF, -1) for _ in range(2 * self.size)]
        self.maxv = [(-INF, -1) for _ in range(2 * self.size)]
        self.lazy = [0] * (2 * self.size)

        # 葉のindexを設定
        for i in range(n):
            pos = i + 1
            self.minv[self.size + i] = (INF, pos)
            self.maxv[self.size + i] = (-INF, pos)

        for i in range(self.size - 1, 0, -1):
            self._pull(i)

    # 子ノードから親ノードを再計算
    def _pull(self, idx):
        self.minv[idx] = min(self.minv[idx * 2], self.minv[idx * 2 + 1], key=lambda x: x[0])
        self.maxv[idx] = max(self.maxv[idx * 2], self.maxv[idx * 2 + 1], key=lambda x: x[0])

    # ノードに遅延を適用
    def _apply(self, idx, val):
        vmin, pmin = self.minv[idx]
        vmax, pmax = self.maxv[idx]
        self.minv[idx] = (vmin + val, pmin)
        self.maxv[idx] = (vmax + val, pmax)
        if idx < self.size:
            self.lazy[idx] += val

    # 遅延を子に伝搬
    def _push(self, idx):
        if self.lazy[idx] != 0:
            self._apply(idx * 2, self.lazy[idx])
            self._apply(idx * 2 + 1, self.lazy[idx])
            self.lazy[idx] = 0

    # 区間加算 [l, r](1-indexed)
    def range_add(self, l, r, val):
        def _range_add(idx, nl, nr):
            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
            _range_add(idx * 2, nl, mid)
            _range_add(idx * 2 + 1, mid + 1, nr)
            self._pull(idx)

        _range_add(1, 1, self.size)

    # 区間最小 (値, index)
    def range_min(self, l, r):
        res = (INF, -1)

        def _range_min(idx, nl, nr):
            nonlocal res
            if r < nl or nr < l:
                return
            if l <= nl and nr <= r:
                res = min(res, self.minv[idx], key=lambda x: x[0])
                return
            self._push(idx)
            mid = (nl + nr) // 2
            _range_min(idx * 2, nl, mid)
            _range_min(idx * 2 + 1, mid + 1, nr)

        _range_min(1, 1, self.size)
        return res

    # 区間最大 (値, index)
    def range_max(self, l, r):
        res = (-INF, -1)

        def _range_max(idx, nl, nr):
            nonlocal res
            if r < nl or nr < l:
                return
            if l <= nl and nr <= r:
                res = max(res, self.maxv[idx], key=lambda x: x[0])
                return
            self._push(idx)
            mid = (nl + nr) // 2
            _range_max(idx * 2, nl, mid)
            _range_max(idx * 2 + 1, mid + 1, nr)

        _range_max(1, 1, self.size)
        return res

    # 1点の値を設定
    def point_set(self, pos, val):
        def _set(idx, nl, nr):
            if nl == nr:
                self.minv[idx] = (val, pos)
                self.maxv[idx] = (val, pos)
                self.lazy[idx] = 0
                return
            self._push(idx)
            mid = (nl + nr) // 2
            if pos <= mid:
                _set(idx * 2, nl, mid)
            else:
                _set(idx * 2 + 1, mid + 1, nr)
            self._pull(idx)

        _set(1, 1, self.size)

    # 1点の値を取得
    def point_get(self, pos):
        def _get(idx, nl, nr):
            if nl == nr:
                return self.minv[idx][0]
            self._push(idx)
            mid = (nl + nr) // 2
            if pos <= mid:
                return _get(idx * 2, nl, mid)
            else:
                return _get(idx * 2 + 1, mid + 1, nr)

        return _get(1, 1, self.size)



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)
0