結果

問題 No.871 かえるのうた
ユーザー kohei2019kohei2019
提出日時 2022-05-04 14:42:57
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 410 ms / 2,000 ms
コード長 13,812 bytes
コンパイル時間 408 ms
コンパイル使用メモリ 87,048 KB
実行使用メモリ 110,948 KB
最終ジャッジ日時 2023-08-20 09:43:37
合計ジャッジ時間 11,295 ms
ジャッジサーバーID
(参考情報)
judge12 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 90 ms
71,632 KB
testcase_01 AC 90 ms
71,672 KB
testcase_02 AC 91 ms
71,584 KB
testcase_03 AC 92 ms
71,700 KB
testcase_04 AC 93 ms
71,496 KB
testcase_05 AC 93 ms
71,784 KB
testcase_06 AC 90 ms
71,808 KB
testcase_07 AC 90 ms
71,580 KB
testcase_08 AC 123 ms
78,004 KB
testcase_09 AC 127 ms
77,804 KB
testcase_10 AC 134 ms
77,912 KB
testcase_11 AC 116 ms
77,876 KB
testcase_12 AC 160 ms
82,856 KB
testcase_13 AC 144 ms
78,632 KB
testcase_14 AC 243 ms
109,960 KB
testcase_15 AC 252 ms
110,484 KB
testcase_16 AC 387 ms
110,948 KB
testcase_17 AC 232 ms
109,412 KB
testcase_18 AC 140 ms
82,468 KB
testcase_19 AC 306 ms
110,800 KB
testcase_20 AC 164 ms
79,868 KB
testcase_21 AC 260 ms
89,404 KB
testcase_22 AC 91 ms
71,752 KB
testcase_23 AC 92 ms
71,632 KB
testcase_24 AC 91 ms
71,712 KB
testcase_25 AC 153 ms
78,544 KB
testcase_26 AC 182 ms
80,268 KB
testcase_27 AC 143 ms
79,616 KB
testcase_28 AC 95 ms
71,584 KB
testcase_29 AC 191 ms
96,652 KB
testcase_30 AC 374 ms
103,556 KB
testcase_31 AC 119 ms
78,376 KB
testcase_32 AC 352 ms
99,384 KB
testcase_33 AC 273 ms
108,284 KB
testcase_34 AC 145 ms
82,972 KB
testcase_35 AC 208 ms
96,660 KB
testcase_36 AC 218 ms
104,104 KB
testcase_37 AC 284 ms
91,136 KB
testcase_38 AC 410 ms
109,544 KB
testcase_39 AC 407 ms
105,888 KB
testcase_40 AC 355 ms
94,088 KB
testcase_41 AC 89 ms
71,616 KB
testcase_42 AC 264 ms
94,164 KB
testcase_43 AC 91 ms
71,708 KB
testcase_44 AC 90 ms
71,492 KB
testcase_45 AC 160 ms
78,348 KB
testcase_46 AC 90 ms
71,584 KB
testcase_47 AC 91 ms
71,668 KB
testcase_48 AC 94 ms
71,592 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#非再帰の平衡二分木
import copy
class Node:
    """ノード

    Attributes:
        key (any): ノードのキー。比較可能なものであれば良い。(1, 4)などタプルも可。
        val (any): ノードの値。
        lch (Node): 左の子ノード。
        rch (Node): 右の子ノード。
        bias (int): 平衡度。(左部分木の高さ)-(右部分木の高さ)。
        size (int): 自分を根とする部分木の大きさ

    """

    def __init__(self, key, val):
        self.key = key
        self.val = val
        self.lch = None
        self.rch = None
        self.bias = 0
        self.size = 1

class AVLTree:
    """非再帰AVL木

    Attributes:
        root (Node): 根ノード。初期値はNone。
        valdefault (any): ノード値のデフォルト値。デフォルトではNone。(数値、リストなど可)

    """

    def __init__(self,valdefault=None):
        self.root = None
        self.valdefault = valdefault
        
    def rotate_left(self, v):
        u = v.rch
        u.size = v.size
        v.size -= u.rch.size + 1 if u.rch is not None else 1
        v.rch = u.lch
        u.lch = v
        if u.bias == -1:
            u.bias = v.bias = 0
        else:
            u.bias = 1
            v.bias = -1
        return u

    def rotate_right(self, v):
        u = v.lch
        u.size = v.size
        v.size -= u.lch.size + 1 if u.lch is not None else 1
        v.lch = u.rch
        u.rch = v
        if u.bias == 1:
            u.bias = v.bias = 0
        else:
            u.bias = -1
            v.bias = 1
        return u

    def rotateLR(self, v):
        u = v.lch
        t = u.rch
        t.size = v.size
        v.size -= u.size - (t.rch.size if t.rch is not None else 0)
        u.size -= t.rch.size + 1 if t.rch is not None else 1
        u.rch = t.lch
        t.lch = u
        v.lch = t.rch
        t.rch = v
        self.update_bias_double(t)
        return t

    def rotateRL(self, v):
        u = v.rch
        t = u.lch
        t.size = v.size
        v.size -= u.size - (t.lch.size if t.lch is not None else 0)
        u.size -= t.lch.size + 1 if t.lch is not None else 1
        u.lch = t.rch
        t.rch = u
        v.rch = t.lch
        t.lch = v
        self.update_bias_double(t)
        return t

    def update_bias_double(self, v):
        if v.bias == 1:
            v.rch.bias = -1
            v.lch.bias = 0
        elif v.bias == -1:
            v.rch.bias = 0
            v.lch.bias = 1
        else:
            v.rch.bias = 0
            v.lch.bias = 0
        v.bias = 0

    def insert(self, key, val=None):
        """挿入

        指定したkeyを挿入する。valはkeyのノード値。

        Args:
            key (any): キー。
            val (any): 値。(指定しない場合はvaldefaultが入る)

        Note:
            同じキーがあった場合は上書きする。

        """
        if val == None:
            val = copy.deepcopy(self.valdefault)
        if self.root is None:
            self.root = Node(key, val)
            return

        v = self.root
        history = []
        while v is not None:
            if key < v.key:
                history.append((v, 1))
                v = v.lch
            elif v.key < key:
                history.append((v, -1))
                v = v.rch
            elif v.key == key:
                v.val = val
                return

        p, pdir = history[-1]
        if pdir == 1:
            p.lch = Node(key, val)
        else:
            p.rch = Node(key, val)

        while history:
            v, direction = history.pop()
            v.bias += direction
            v.size += 1

            new_v = None
            b = v.bias
            if b == 0:
                break

            if b == 2:
                u = v.lch
                if u.bias == -1:
                    new_v = self.rotateLR(v)
                else:
                    new_v = self.rotate_right(v)
                break
            if b == -2:
                u = v.rch
                if u.bias == 1:
                    new_v = self.rotateRL(v)
                else:
                    new_v = self.rotate_left(v)
                break

        if new_v is not None:
            if len(history) == 0:
                self.root = new_v
                return
            p, pdir = history.pop()
            p.size += 1
            if pdir == 1:
                p.lch = new_v
            else:
                p.rch = new_v

        while history:
            p, pdir = history.pop()
            p.size += 1

    def delete(self, key):
        """削除

        指定したkeyの要素を削除する。

        Args:
            key (any): キー。

        Return:
            bool: 指定したキーが存在するならTrue、しないならFalse。

        """
        v = self.root
        history = []
        while v is not None:
            if key < v.key:
                history.append((v, 1))
                v = v.lch
            elif v.key < key:
                history.append((v, -1))
                v = v.rch
            else:
                break
        else:
            return False

        if v.lch is not None:
            history.append((v, 1))
            lmax = v.lch
            while lmax.rch is not None:
                history.append((lmax, -1))
                lmax = lmax.rch

            v.key = lmax.key
            v.val = lmax.val

            v = lmax

        c = v.rch if v.lch is None else v.lch

        if history:
            p, pdir = history[-1]
            if pdir == 1:
                p.lch = c
            else:
                p.rch = c
        else:
            self.root = c
            return True

        while history:
            new_p = None

            p, pdir = history.pop()
            p.bias -= pdir
            p.size -= 1

            b = p.bias
            if b == 2:
                if p.lch.bias == -1:
                    new_p = self.rotateLR(p)
                else:
                    new_p = self.rotate_right(p)

            elif b == -2:
                if p.rch.bias == 1:
                    new_p = self.rotateRL(p)
                else:
                    new_p = self.rotate_left(p)

            elif b != 0:
                break

            if new_p is not None:
                if len(history) == 0:
                    self.root = new_p
                    return True
                gp, gpdir = history[-1]
                if gpdir == 1:
                    gp.lch = new_p
                else:
                    gp.rch = new_p
                if new_p.bias != 0:
                    break

        while history:
            p, pdir = history.pop()
            p.size -= 1

        return True

    def member(self, key):
        """キーの存在チェック

        指定したkeyがあるかどうか判定する。

        Args:
            key (any): キー。

        Return:
            bool: 指定したキーが存在するならTrue、しないならFalse。

        """
        v = self.root
        while v is not None:
            if key < v.key:
                v = v.lch
            elif v.key < key:
                v = v.rch
            else:
                return True
        return False

    def getval(self, key):
        """値の取り出し

        指定したkeyの値を返す。

        Args:
            key (any): キー。

        Return:
            any: 指定したキーが存在するならそのオブジェクト。存在しなければvaldefault

        """
        v = self.root
        while v is not None:
            if key < v.key:
                v = v.lch
            elif v.key < key:
                v = v.rch
            else:
                return v.val
        self.insert(key)
        return self[key] #

    def lower_bound(self, key):
        """下限つき探索

        指定したkey以上で最小のキーを見つける。[key,inf)で最小

        Args:
            key (any): キーの下限。

        Return:
            any: 条件を満たすようなキー。そのようなキーが一つも存在しないならNone。

        """
        ret = None
        v = self.root
        while v is not None:
            if v.key >= key:
                if ret is None or ret > v.key:
                    ret = v.key
                v = v.lch
            else:
                v = v.rch
        return ret

    def upper_bound(self, key):
        """上限つき探索

        指定したkey未満で最大のキーを見つける。[-inf,key)で最大

        Args:
            key (any): キーの上限。

        Return:
            any: 条件を満たすようなキー。そのようなキーが一つも存在しないならNone。

        """
        ret = None
        v = self.root
        while v is not None:
            if v.key < key:
                if ret is None or ret < v.key:
                    ret = v.key
                v = v.rch
            else:
                v = v.lch
        return ret

    def find_kth_element(self, k):
        """小さい方からk番目の要素を見つける

        Args:
            k (int): 何番目の要素か(0オリジン)。

        Return:
            any: 小さい方からk番目のキーの値。
        """
        v = self.root
        s = 0
        while v is not None:
            t = s+v.lch.size if v.lch is not None else s
            if t == k:
                return v.key
            elif t < k:
                s = t+1
                v = v.rch
            else:
                v = v.lch
        return None

    def key_kth(self,key):
        '''
        Args:
            keyが何番目に小さい要素かを調べる
        
        Return:
            int(keyが存在しなければNone)
        '''
        v = self.root
        kth = 0
        f = False
        while v is not None:
            if key < v.key:
                v = v.lch
            elif v.key < key:
                kth += 1+v.lch.size if v.lch is not None else 1
                v = v.rch
            else:
                kth += v.lch.size if v.lch is not None else 0
                f = True
                break
        if f:
            return kth
        else:
            return None

    def getmin(self):
        '''
        Return:
            any: 存在するキーの最小値
        '''
        if len(self) == 0:
            raise('empty')
        ret = None
        v = self.root
        while True:
            ret = v
            v = v.lch
            if v == None:
                break
        return ret.key
    
    def getmax(self):
        '''
        Return:
            any: 存在するキーの最大値
        '''
        if len(self) == 0:
            raise('empty')
        ret = None
        v = self.root
        while True:
            ret = v
            v = v.rch
            if v == None:
                break
        return ret.key
    
    def popmin(self):
        '''
        存在するキーの最小値をpopする
        Return:
            any: popした値
        '''
        if len(self) == 0:
            raise('empty')
        ret = None
        v = self.root
        while True:
            ret = v
            v = v.lch
            if v == None:
                break      
        del self[ret.key]
        return ret.key
    
    def popmax(self):
        '''
        存在するキーの最大値をpopする
        Return:
            any: popした値
        '''
        if len(self) == 0:
            raise('empty')
        ret = None
        v = self.root
        while True:
            ret = v
            v = v.rch
            if v == None:
                break
        del self[ret.key]
        return ret.key

    def popkth(self,k):
        '''
        存在するキーの小さい方からk番目をpopする
        Return:
            any: popした値
        '''
        key = self.find_kth_element(k)
        del self[key]
        return key
    
    def get_key_val(self):
        '''
        Return:
            dict: 存在するキーとノード値をdictで出力
        '''
        retdict = dict()
        for i in range(len(self)):
            key = self.find_kth_element(i)
            val = self[key]
            retdict[key] = val
        return retdict
    
    def values(self):
        for i in range(len(self)):
            yield self[self.find_kth_element(i)]

    def keys(self):
        for i in range(len(self)):
            yield self.find_kth_element(i)
    
    def items(self):
        for i in range(len(self)):
            key = self.find_kth_element(i)
            yield key,self[key]

    def __iter__(self): return self.keys()
    def __contains__(self, key): return self.member(key)
    def __getitem__(self, key): return self.getval(key)
    def __setitem__(self, key, val): return self.insert(key, val)
    def __delitem__(self, key): return self.delete(key)
    def __bool__(self): return self.root is not None
    def __len__(self): return self.root.size if self.root is not None else 0
    def __str__(self): return str(type(self))+'('+str(self.get_key_val())+')'

N,K = map(int,input().split())
lsX = list(map(int,input().split()))
lsA = list(map(int,input().split()))
AT = AVLTree()
for i in range(N):
    AT.insert((lsX[i],i))
f = True
l,r = lsX[K-1]-lsA[K-1],lsX[K-1]+lsA[K-1]
ans = 1
AT.delete((lsX[K-1],K-1))
while f:
    ln,rn = l,r
    while AT.lower_bound((l,0)) != None and AT.lower_bound((l,0)) <=(r,N+1):
        k = AT.lower_bound((l,0))
        ln = min(ln,k[0]-lsA[k[1]])
        rn = max(rn,k[0]+lsA[k[1]])
        AT.delete(k)
        ans += 1
    if ln == l and rn == r:
        break
    l,r = ln,rn
print(ans)
0