python线段树

        ps = [0] + list(accumulate(b)) 
        Sigma = lambda i,j : ps[j+1] - ps[i]
N = 100<<10 
bit_length = [0] * N
for i in range(1,N):  
    bit_length[i] = bit_length[i>>1] + 1
class ST:
    def __init__(self,A,func=max):
        dp = A[:]
        self.st = st = [dp]
        self.func = func
        j, N = 1, len(dp)
        while 2*j<=N:
            dp = [func(dp[i],dp[i+j]) for i in range(N-2*j+1)]
            st.append(dp)
            j <<= 1 
    def query(self,l,r):
        j = bit_length[r-l+1]-1
        return self.func(self.st[j][l],self.st[j][r-(1<<j)+1]) 
        b1 = BIT(n,0,inf,min) 
class BIT:
    def __init__(self,n, postfix, default_val, reduce_op, sizeQ = 10**5):
        self.N =  n + 2  
        self.postfix = postfix 
        self.default_val = default_val
        self.reduce_op = reduce_op
        self.A =  [default_val] * self.N if n < sizeQ*n.bit_length()  \
            else defaultdict(lambda:default_val)
    def add(self,i,x):
        i = i+1 if not self.postfix else self.N-(i+1) 
        if i <=0 : i = 1  
        while i < self.N:  
            self.A[i] = self.reduce_op(self.A[i],x)
            i += -i & i 
    def get(self,i):
        i = i+1 if not self.postfix else self.N-(i+1)  
        if i >= self.N : i = self.N - 1 
        res = self.default_val
        while i > 0: 
            res = self.reduce_op(res,self.A[i])
            i ^= -i & i  
        return res 

class SEGMENTTREE:
    def __init__(self, n):
        n += 2
        self.N = 1 << (n-1).bit_length()
        self.n = n  
        self.default_val = default_val  = 0 ########
        self.A = [default_val for _ in  range(n + self.N) ]  
        self.reduce_op = max #####
    # def reduce_op(self,a,b):  #####
    def _set(self,i,x):   #######
        self.A[i] = max(x,self.A[i])
    def build(self,_A):
        l = self.N 
        r = self.N + len(_A)-1 
        for i,x in enumerate(_A,l): 
            self._set(i,x)  
        while l > 1:
            l >>= 1 
            r >>= 1 
            for i in range(l,r+1): 
                self.A[i] = self.reduce_op(self.A[i<<1],self.A[i<<1|1])
    def set(self,i,x):
        i += self.N 
        self._set(i,x) 
        while i > 1:  
            i >>= 1 
            self.A[i] = self.reduce_op(self.A[i<<1],self.A[i<<1|1]) 
    def get(self,i) : return self.A[l + self.N]
    def queryAll(self) : return self.A[1]
    def query(self,l,r ): 
        l = max(0,l) + self.N 
        r = min(self.n-1,r) + self.N 
        res = self.default_val 
        while l <= r : 
            if l & 1 == 1: res = self.reduce_op(self.A[l],res) 
            if r & 1 == 0: res = self.reduce_op(res, self.A[r])
            l = l + 1 >> 1 
            r = r - 1 >> 1 
        return res
区间0-1翻转 求1个数
        tree = LAZY_SEGMENTTREE(
            defaultval = 0 ,
            defaultlazy = 0 , 
            left = 0, right = n,
            reduce_op = lambda val1,val2:  val1 + val2,
            lazy_op = lambda lazy0,lz :  lazy0 ^ lz, 
            lazy_val = lambda l,r,lz,val0: (r-l+1)-val0 if lz else val0 
        )
区间赋值
        tree  = LAZY_SEGMENTTREE(
            defaultval = 0 ,
            defaultlazy = inf , 
            left = 0, right = 10**9,
            reduce_op = lambda val1,val2:  val1 + val2,
            lazy_op = lambda lazy0,lz :   lz, 
            lazy_val = lambda l,r,lz,val0: lz*(r-l+1) if lz != inf else val0 
        )
区间增加
        tree  = LAZY_SEGMENTTREE(
            defaultval = 0 ,
            defaultlazy = 0 , 
            left = 0, right = 10**9,
            reduce_op = lambda val1,val2:  val1 + val2,
            lazy_op = lambda lazy0,lz :  lazy0 + lz, 
            lazy_val = lambda l,r,lz,val0: val0+lz*(r-l+1)
        )
区间最大值
        tree = LAZY_SEGMENTTREE(
            defaultval = 0 ,
            defaultlazy = 0 , 
            left= 0, right = max(nums),
            reduce_op = lambda val1,val2:  val1 if val1 > val2 else val2,
            lazy_op = lambda lazy0,lz :   lazy0 if lazy0 > lz else lz, 
            lazy_val = lambda l,r,lz,val0: lz if lz > val0 else val0 
        ) 
class LAZY_SEGMENTTREE:
    def __init__(self,
            defaultval = 0 ,
            defaultlazy = 0 , 
            left = 0, right = 10**9,
            reduce_op = lambda val1,val2:  val1 + val2,
            lazy_op = lambda lazy0,lz :  lazy0 + lz, 
            lazy_val = lambda l,r,lz,val0: val0+lz*(r-l+1)
        ):
        self.defaultval = defaultval
        self.defaultlazy = defaultlazy
        self.left = left 
        self.right = right 
        self.reduce_op = reduce_op
        self.lazy_op = lazy_op
        self.lazy_val = lazy_val
        self.val = defaultdict(lambda:defaultval)
        self.lazy = defaultdict(lambda:defaultlazy) 
    def lazy_do(self,i,l,r,lz):
        self.val[i] = self.lazy_val(l,r,lz,self.val[i])
        self.lazy[i] = self.lazy_op(self.lazy[i],lz)
    def update(self,start,end,lz):
        return self._update(start,end,self.left,self.right,lz,1) 
    def query(self,start,end):
        return self._query(start,end,self.left,self.right,1)
    def _down(self, i, l , r):
        mid = (l + r) // 2
        if self.lazy[i] != self.defaultlazy :
            self.lazy_do(i*2,l, mid,self.lazy[i]) 
            self.lazy_do(i*2+1,mid + 1, r,self.lazy[i]) 
            self.lazy[i] = self.defaultlazy
        return mid 
    def _update(self, start, end, l, r, lz, i ):  
        if start <= l and r <= end:  
            self.lazy_do(i,l,r,lz)
        else:
            mid = self._down(i, l , r) 
            if mid >= start : self._update(start, end, l, mid, lz, i * 2,)
            if mid+1 <= end : self._update(start, end, mid + 1, r, lz, i * 2 + 1) 
            self.val[i] = self.reduce_op(self.val[i*2] , self.val[i*2+1])
    def _query(self,start, end, l, r, i): 
        if start <= l and r <= end: return self.val[i]
        else:
            mid = self._down( i, l , r) 
            res = self.defaultval 
            if mid >= start : res = self.reduce_op(self._query(start, end, l, mid, i * 2),res )
            if mid+1 <= end : res = self.reduce_op(res,self._query(start, end, mid + 1, r, i * 2 + 1) ) 
            return res 
    def build(self, A, i=0 ,l=0 ,r=-1 ):  
        if l == r: self.val[i] = A[l]
        elif r==-1: 
            self.left,self.right = 0,len(A)-1 
            self.build(A,1,0,len(A)-1)
        else : 
            mid = (l+r) // 2
            self.build(A, i*2,l,mid)
            self.build(A, i*2+1,mid+1,r)
            self.val[i] = self.reduce_op(self.val[i*2],self.val[i*2+1])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对算法有兴趣的可以来看看 在自然数,且所有的数不大于30000的范围内讨论一个问题:现在已知n条线段,把端点依次输入告诉你,然后有m个询问,每个询问输入一个点,要求这个点在多少条线段上出现过; 最基本的解法当然就是读一个点,就把所有线段比一下,看看在不在线段中; 每次询问都要把n条线段查一次,那么m次询问,就要运算m*n次,复杂度就是O(m*n) 这道题m和n都是30000,那么计算量达到了10^9;而计算机1秒的计算量大约是10^8的数量级,所以这种方法无论怎么优化都是超时 因为n条线段是固定的,所以某种程度上说每次都把n条线段查一遍有大量的重复和浪费; 线段树就是可以解决这类问题的数据结构 举例说明:已知线段[2,5] [4,6] [0,7];求点2,4,7分别出现了多少次 在[0,7]区间上建立一棵满二叉树:(为了和已知线段区别,用【】表示线段树中的线段) 【0,7】 / \ 【0,3】 【4,7】 / \ / \ 【0,1】 【2,3】 【4,5】 【6,7】 / \ / \ / \ / \ 【0,0】 【1,1】 【2,2】 【3,3】 【4,4】 【5,5】 【6,6】 【7,7】 每个节点用结构体: struct line { int left,right; // 左端点、右端点 int n; // 记录这条线段出现了多少次,默认为0 }a[16]; 和堆类似,满二叉树的性质决定a[i]的左儿子是a[2*i]、右儿子是a[2*i+1]; 然后对于已知的线段依次进行插入操作: 从树根开始调用递归函数insert // 要插入的线段的左端点和右端点、以及当前线段树中的某条线段 void insert(int s,int t,int step)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值