結果

問題 No.2421 entersys?
ユーザー kemunikukemuniku
提出日時 2023-08-12 14:57:49
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 1,657 ms / 3,000 ms
コード長 8,285 bytes
コンパイル時間 276 ms
コンパイル使用メモリ 82,656 KB
実行使用メモリ 263,524 KB
最終ジャッジ日時 2024-04-30 07:39:48
合計ジャッジ時間 28,707 ms
ジャッジサーバーID
(参考情報)
judge3 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 56 ms
69,044 KB
testcase_01 AC 101 ms
78,200 KB
testcase_02 AC 136 ms
79,868 KB
testcase_03 AC 76 ms
78,140 KB
testcase_04 AC 103 ms
78,452 KB
testcase_05 AC 122 ms
79,864 KB
testcase_06 AC 132 ms
79,988 KB
testcase_07 AC 125 ms
79,784 KB
testcase_08 AC 138 ms
79,848 KB
testcase_09 AC 155 ms
79,724 KB
testcase_10 AC 115 ms
79,452 KB
testcase_11 AC 1,452 ms
233,344 KB
testcase_12 AC 1,452 ms
234,364 KB
testcase_13 AC 1,455 ms
234,364 KB
testcase_14 AC 1,482 ms
234,204 KB
testcase_15 AC 1,480 ms
233,856 KB
testcase_16 AC 1,432 ms
233,348 KB
testcase_17 AC 1,445 ms
233,804 KB
testcase_18 AC 1,502 ms
233,668 KB
testcase_19 AC 1,443 ms
234,344 KB
testcase_20 AC 1,449 ms
233,680 KB
testcase_21 AC 1,150 ms
231,248 KB
testcase_22 AC 1,177 ms
213,596 KB
testcase_23 AC 1,639 ms
262,848 KB
testcase_24 AC 1,587 ms
262,636 KB
testcase_25 AC 1,657 ms
263,524 KB
testcase_26 AC 1,048 ms
230,576 KB
testcase_27 AC 1,026 ms
230,656 KB
testcase_28 AC 1,023 ms
231,860 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

# https://github.com/tatyam-prime/SortedSet/blob/main/SortedMultiset.py
import math
from bisect import bisect_left, bisect_right, insort
from typing import Generic, Iterable, Iterator, TypeVar, Union, List
T = TypeVar('T')

class SortedMultiset(Generic[T]):
    BUCKET_RATIO = 50
    REBUILD_RATIO = 170

    def _build(self, a=None) -> None:
        "Evenly divide `a` into buckets."
        if a is None: a = list(self)
        size = self.size = len(a)
        bucket_size = int(math.ceil(math.sqrt(size / self.BUCKET_RATIO)))
        self.a = [a[size * i // bucket_size : size * (i + 1) // bucket_size] for i in range(bucket_size)]
    
    def __init__(self, a: Iterable[T] = []) -> None:
        "Make a new SortedMultiset from iterable. / O(N) if sorted / O(N log N)"
        a = list(a)
        if not all(a[i] <= a[i + 1] for i in range(len(a) - 1)):
            a = sorted(a)
        self._build(a)

    def __iter__(self) -> Iterator[T]:
        for i in self.a:
            for j in i: yield j

    def __reversed__(self) -> Iterator[T]:
        for i in reversed(self.a):
            for j in reversed(i): yield j
    
    def __len__(self) -> int:
        return self.size
    
    def __repr__(self) -> str:
        return "SortedMultiset" + str(self.a)
    
    def __str__(self) -> str:
        s = str(list(self))
        return "{" + s[1 : len(s) - 1] + "}"

    def _find_bucket(self, x: T) -> List[T]:
        "Find the bucket which should contain x. self must not be empty."
        for a in self.a:
            if x <= a[-1]: return a
        return a

    def __contains__(self, x: T) -> bool:
        if self.size == 0: return False
        a = self._find_bucket(x)
        i = bisect_left(a, x)
        return i != len(a) and a[i] == x

    def count(self, x: T) -> int:
        "Count the number of x."
        return self.index_right(x) - self.index(x)

    def add(self, x: T) -> None:
        "Add an element. / O(√N)"
        if self.size == 0:
            self.a = [[x]]
            self.size = 1
            return
        a = self._find_bucket(x)
        insort(a, x)
        self.size += 1
        if len(a) > len(self.a) * self.REBUILD_RATIO:
            self._build()

    def discard(self, x: T) -> bool:
        "Remove an element and return True if removed. / O(√N)"
        if self.size == 0: return False
        a = self._find_bucket(x)
        i = bisect_left(a, x)
        if i == len(a) or a[i] != x: return False
        a.pop(i)
        self.size -= 1
        if len(a) == 0: self._build()
        return True

    def lt(self, x: T) -> Union[T, None]:
        "Find the largest element < x, or None if it doesn't exist."
        for a in reversed(self.a):
            if a[0] < x:
                return a[bisect_left(a, x) - 1]

    def le(self, x: T) -> Union[T, None]:
        "Find the largest element <= x, or None if it doesn't exist."
        for a in reversed(self.a):
            if a[0] <= x:
                return a[bisect_right(a, x) - 1]

    def gt(self, x: T) -> Union[T, None]:
        "Find the smallest element > x, or None if it doesn't exist."
        for a in self.a:
            if a[-1] > x:
                return a[bisect_right(a, x)]

    def ge(self, x: T) -> Union[T, None]:
        "Find the smallest element >= x, or None if it doesn't exist."
        for a in self.a:
            if a[-1] >= x:
                return a[bisect_left(a, x)]
    
    def __getitem__(self, x: int) -> T:
        "Return the x-th element, or IndexError if it doesn't exist."
        if x < 0: x += self.size
        if x < 0: raise IndexError
        for a in self.a:
            if x < len(a): return a[x]
            x -= len(a)
        raise IndexError

    def index(self, x: T) -> int:
        "Count the number of elements < x."
        ans = 0
        for a in self.a:
            if a[-1] >= x:
                return ans + bisect_left(a, x)
            ans += len(a)
        return ans

    def index_right(self, x: T) -> int:
        "Count the number of elements <= x."
        ans = 0
        for a in self.a:
            if a[-1] > x:
                return ans + bisect_right(a, x)
            ans += len(a)
        return ans
class SegmentTree:
    def __init__(self, v,marge,default):
        self.default = default
        self.marge = marge
        self.lastnode = 1
        self.h = 1
        while self.lastnode < len(v):
            self.lastnode*=2
            self.h += 1
        #1-indexedで作成する
        self.array = [self.default] *(2*self.lastnode)
        self.lazy = [0] *(2*self.lastnode)
        for i in range(len(v)):
            self.array[self.lastnode+i] = v[i]
        for i in range(self.lastnode-1,-1,-1):
            self.array[i] = self.marge(self.array[2*i],self.array[2*i+1])
    def propagate(self,i):
        if self.lazy[i] != 0:
            v = self.lazy[i] #下に伝播させるやつ
            if i < self.lastnode:
                self.lazy[i] = 0
                self.lazy[2*i]+= v
                self.lazy[2*i+1] += v
                self.array[2*i] += v
                self.array[2*i+1] += v
            self.lazy[i] = 0
    def eval(self,L,R):
        L+=self.lastnode
        R+=self.lastnode
        L0 = L // (L & -L)  # 奇数になるまで L を 2 で割ったもの
        R0 = R // (R & -R)  # 奇数になるまで R を 2 で割ったもの
        H = L0.bit_length() - 1
        for n in range(H, -1, -1):
            self.propagate(L0>>n)
        H = R0.bit_length() - 1
        for n in range(H, -1, -1):
            self.propagate(R0>>n)
        
    def recalc(self,L,R):
        L+=self.lastnode
        R+=self.lastnode
        L0 = L // (L & -L)  # 奇数になるまで L を 2 で割ったもの
        R0 = R // (R & -R)  # 奇数になるまで R を 2 で割ったもの
        while L0 > 1:
            L0 >>= 1
            self.array[L0] = self.marge(self.array[2*L0],self.array[2*L0+1])
        while R0 > 1:
            R0 >>= 1
            self.array[R0] = self.marge(self.array[2*R0],self.array[2*R0+1])
    def add(self,q_left , q_right,val):
        self.eval(q_left , q_right)
        L,R = q_left, q_right
        q_left += self.lastnode
        q_right += self.lastnode
        while q_left < q_right:
            if q_left&1:
                self.array[q_left] += val
                self.lazy[q_left] += val
                q_left += 1
            if q_right&1:
                q_right -= 1
                self.array[q_right] +=val
                self.lazy[q_right] += val
            q_left >>= 1
            q_right>>= 1
        self.recalc(L,R)
    def query(self,q_left,q_right):
        self.eval(q_left , q_right)
        q_left += self.lastnode
        q_right += self.lastnode
        
        lres,rres = self.default,self.default
        while q_left < q_right:
            if q_left&1:
                lres = self.marge(lres,self.array[q_left])
                q_left += 1
            if q_right&1:
                q_right -= 1
                rres = self.marge(self.array[q_right],rres)
            q_left >>= 1
            q_right>>= 1
        return self.marge(lres,rres)
 
from collections import defaultdict
N = int(input())

enter = defaultdict(SortedMultiset)
info = []
times = set()
for i in range(N):
  X,L,R = input().split()
  L = int(L)
  R = int(R)
  info.append((X,L,R))
  times.add(L)
  times.add(R)
Q = int(input())
querys = []
for i in range(Q):
  q,*arg = input().split()
  q = int(q)
  querys.append((q,arg))
  if q == 1:
    times.add(int(arg[1]))
  elif q == 2:
    times.add(int(arg[0]))
  else:
    times.add(int(arg[1]))
    times.add(int(arg[2]))
compttmp = sorted(list(times))
compt = {compttmp[i]:i for i in range(len(compttmp))}
st = SegmentTree([0]*len(compt),lambda x,y:x+y,0)
for X,L,R in info:
  enter[X].add((L,R))
  st.add(compt[L],compt[R]+1,1)
for q,arg in querys:
  if q == 1:
    x,t = arg
    t = int(t)
    z = enter[x].lt((t,10**18))
    if z is None:
      print("No")
    else:
      l,r = z
      if l <= t <= r:
        print("Yes")
      else:
        print("No")
  elif q == 2:
    t = int(arg[0])
    print(st.query(compt[t],compt[t]+1))
  else:
    x,l,r = arg
    l = int(l)
    r = int(r)
    enter[x].add((l,r))    
    st.add(compt[l],compt[r]+1,1)
0