abcsumits's blog

By abcsumits, history, 9 months ago, In English

It uses radix trie , where each node contains its subtrees leaf node count to index. And lower bound and upper bound are calculated based on last node that had other way to go if the current path doesnt leads to a leaf. Insertion and deletion has complexity of O(log(m)) where m is the integer we want to insert(basically that of a radix trie)

class intOrderedListNode:
    def __init__(self):
        self.zero_next=None
        self.zero_size=0
        self.one_next=None
        self.one_size=0
class intOrderedList(intOrderedListNode):
    def __init__(self):
        self.node=intOrderedListNode()
        self.max_depth=1
        self.size=0
    def insert(self, value: int) -> None:
        while self.max_depth<value:
            temp=self.node
            self.node=intOrderedListNode()
            self.node.zero_next=temp
            self.node.zero_size=temp.zero_size+temp.one_size
            self.max_depth<<=1
        temp=self.max_depth
        itr=self.node
        while temp>0:
            if value&temp:
                itr.one_size+=1
                if itr.one_next is None:
                    itr.one_next=intOrderedListNode()
                itr=itr.one_next
            else:
                itr.zero_size+=1
                if itr.zero_next is None:
                    itr.zero_next=intOrderedListNode()
                itr=itr.zero_next
            temp>>=1
        self.size+=1
    def __iter__(self):
        self.idx=0
        return self
    def __next__(self):
        if self.idx>=self.size:
            raise StopIteration
        result=self.index(self.idx)
        self.idx+=1
        return result
    def index(self, idx: int) -> int:
        if idx<0 or idx>=self.size:
            raise IndexError
        result=0
        temp=self.max_depth
        itr=self.node
        while temp>0:
            if itr.zero_size>idx:
                itr=itr.zero_next
            else:
                result|=temp
                idx-=itr.zero_size
                itr=itr.one_next
            temp>>=1
        return result
    def __len__(self):
        return self.size
    def __contains__(self, value: int) -> bool:
        temp=self.max_depth
        itr=self.node
        while temp>0:
            if value&temp:
                if itr.one_size==0:
                    return False
                itr=itr.one_next
            else:
                if itr.zero_size==0:
                    return False
                itr=itr.zero_next
            temp>>=1
        return True
    def lower_bound(self, value: int) -> int:
        temp=self.max_depth
        itr=self.node
        result=0
        last=None
        last_temp=temp
        chk=1
        while temp>0:
            if value&temp:
                if chk:
                    result+=itr.zero_size
                if itr.one_next :
                    itr=itr.one_next
                else:
                    if last:
                        itr=last
                        itr=itr.zero_next
                        temp=last_temp
                        chk=0
                        value=0
                    else:
                        return self.size
                    
            else:
                if itr.zero_next:
                    if itr.one_next:
                        last=itr
                        last_temp=temp
                    itr=itr.zero_next
                else:
                    itr=itr.one_next
                    chk=0
                    value=0
            temp>>=1
        return result
    def upper_bound(self, value: int) -> int:   
        temp=self.max_depth
        itr=self.node
        result=0
        last=None
        last_temp=temp
        chk=1
        while temp>0:
            if value&temp:
                result+=itr.zero_size
                if itr.one_next :
                    if temp==1 and chk:
                        result+=itr.one_size
                    itr=itr.one_next
                else:
                    if last:
                        itr=last
                        itr=itr.zero_next
                        temp=last_temp
                        value=0
                    else:
                        return self.size
                    
            else:
                if itr.zero_next:
                    if itr.one_next:
                        last=itr
                        last_temp=temp
                    if temp==1 and chk:
                        result+=itr.zero_size
                    itr=itr.zero_next
                else:
                    itr=itr.one_next
                    chk=0
                    value=0
            temp>>=1
        return result
    def pop(self, idx: int) -> int:
        if idx<0 or idx>=self.size:
            raise IndexError
        temp=self.max_depth
        itr=self.node
        result=0
        while temp>0:
            if itr.zero_size>idx:
                itr.zero_size-=1
                if itr.zero_size==0:
                    itr.zero_next=None
                itr=itr.zero_next
            else:
                result|=temp
                itr.one_size-=1
                if itr.one_size==0:
                    itr.one_next=None
                idx-=itr.zero_size
                itr=itr.one_next
            temp>>=1
        self.size-=1
        while self.node.one_size==0:
            self.node=self.node.zero_next
            self.max_depth>>=1
        return result

  • Vote: I like it
  • -10
  • Vote: I do not like it