aacord’s memo

abcを中心にpythonで解いた問題のメモ、整理をしています。緑になった。

abc 128 E - Roadwork (python)

セグ木の練習。木というているけど、使いどころはグラフ問題ではなく、ソートされた数列で、特定の区間の最小値や公約数を求めたり、特定の区間の値を変更するときに使う。
愚直にやると N^2かかるが、heap を使おうとすると頭が痛くなるときに便利。
今回の問題は位置 x で通行止めになるスタート時刻の範囲は s,t,x から [s-x,t-x) と作れて、
bisect で D のうち [s-x.t-x) に収まるもの範囲を調べて、その範囲をセグ木を使って x が最小値になれば update させる。

import sys
input = sys.stdin.readline
from bisect import bisect_left

class SegmentTree:
    def __init__(self, n, ele, segfun):
        self.ide_ele = ele
        self.segfun = segfun
        self.n = n
        self.N0 = 1 << n.bit_length()
        self.data = [self.ide_ele] * (self.N0 * 2)

    def update(self, l, r, val):
        l += self.N0
        r += self.N0
        while l < r:
            if l & 1:
                self.data[l] = self.segfun(self.data[l], val)
                l += 1
            if r & 1:
                self.data[r - 1] = self.segfun(self.data[r - 1], val)
                r -= 1
            l //= 2
            r //= 2

    def query(self, i):
        i += len(self.data) // 2
        ret = self.data[i]
        while i > 0:
            i //= 2
            ret = self.segfun(ret, self.data[i])
        return ret

n,q = map(int,input().split())
chk = []
for i in range(n):
  s,t,x = map(int,input().split())
  chk.append((s-x,t-x,x))
  
d = [int(input()) for i in range(q)]
seg = SegmentTree(q,10**9+1,lambda a, b: min(a,b)) 
#個数、モノイド、最小値の順に設定

for a,b,x in chk:
  L = bisect_left(d,a) #範囲を調べる
  R = bisect_left(d,b)
  seg.update(L,R,x) #セグ木で x の最小値を更新
  
for i in range(q):
  m = seg.query(i)
  if m == 10**9+1:
    print(-1)
  else:
    print(m)