python:线段树区间修改 + 区间查询 模板 + 坑点总结
from functools import reduceclass SegTree:'''支持增量更新,覆盖更新,序列更新,任意RMQ操作基于二叉树实现初始化:O(1)增量更新或覆盖更新的单次操作复杂度:O(log k)序列更新的单次复杂度:O(n)'''def __init__(self, f1, f2, l, r, v = 0):'''初始化线段树[left,right)f1,f2示例:线段和:f1=lambda a,b:a+b f2=lambda a,n:a*n线段最大值:f1=lambda a,b:max(a,b)f2=lambda a,n:a线段最小值:f1=lambda a,b:min(a,b)f2=lambda a,n:a'''self.ans = f2(v,r-l)self.f1 = f1self.f2 = f2self.l = l #leftself.r = r #rightself.v = v #init valueself.lazy_tag = 0 #Lazy tagself.left = None #SubTree(left,bottom)self.right = None #SubTree(right,bottom)@propertydef mid_h(self):return (self.l + self.r) // 2def create_subtrees(self):midh = self.mid_hif not self.left and midh > self.l:self.left = SegTree(self.f1, self.f2, self.l, midh)if not self.right:self.right = SegTree(self.f1, self.f2, midh, self.r)def init_seg(self, M):'''将线段树的值初始化为矩阵Matrx输入保证Matrx与线段大小一致'''m0 = M[0]self.lazy_tag = 0for a in M:if a!=m0:breakelse:self.v = m0self.ans = self.f2(m0,len(M))return self.ansself.v = '#'midh = self.mid_hself.create_subtrees()self.ans = self.f1(self.left.init_seg(M[:midh-self.l]), self.right.init_seg(M[midh-self.l:]))return self.ansdef cover_seg(self, l, r, v):'''将线段[left,right)覆盖为val'''if self.v == v or l >= self.r or r <= self.l:return self.ansif l <= self.l and r >= self.r:self.v = vself.lazy_tag = 0self.ans = self.f2(v,self.r-self.l)return self.ansself.create_subtrees()if self.v != '#':if self.left:self.left.v = self.vself.left.ans = self.f2(self.v,self.left.r-self.left.l)if self.right:self.right.v = self.vself.right.ans = self.f2(self.v,self.right.r-self.right.l)self.v = '#'#push upself.ans = self.f1(self.left.cover_seg(l, r, v),self.right.cover_seg(l, r, v))return self.ansdef inc_seg(self, l, r, v):'''将线段[left,right)增加val'''if v == 0 or l >= self.r or r <= self.l:return self.ans#self.ans = '?'if l <= self.l and r >= self.r:if self.v == '#':self.lazy_tag += velse:self.v += vself.ans += self.f2(v,self.r-self.l)return self.ansself.create_subtrees()if self.v != '#':self.left.v = self.vself.left.ans = self.f2(self.v,self.left.r-self.left.l)self.right.v = self.vself.right.ans = self.f2(self.v,self.right.r-self.right.l)self.v = '#'self.pushdown()self.ans = self.f1(self.left.inc_seg(l, r, v),self.right.inc_seg(l, r, v))return self.ansdef inc_idx(self, idx, v):'''increase idx by val'''if v == 0 or idx >= self.r or idx < self.l:return self.ansif idx == self.l == self.r - 1:self.v += vself.ans += self.f2(v,1)return self.ansself.create_subtrees()if self.v != '#':self.left.v = self.vself.left.ans = self.f2(self.v,self.left.r-self.left.l)self.right.v = self.vself.right.ans = self.f2(self.v,self.right.r-self.right.l)self.v = '#'self.pushdown()self.ans = self.f1(self.left.inc_idx(idx, v),self.right.inc_idx(idx, v))return self.ansdef pushdown(self):if self.lazy_tag != 0:if self.left:if self.left.v != '#':self.left.v += self.lazy_tagself.left.lazy_tag = 0else:self.left.lazy_tag += self.lazy_tagself.left.ans += self.f2(self.lazy_tag, self.left.r-self.left.l)if self.right:if self.right.v != '#':self.right.v += self.lazy_tagself.right.lazy_tag = 0else:self.right.lazy_tag += self.lazy_tagself.right.ans += self.f2(self.lazy_tag, self.right.r-self.right.l)self.lazy_tag = 0def query(self, l, r):'''查询线段[right,bottom)的RMQ'''if l>=r: return 0if l <= self.l and r >= self.r:return self.ansif self.v != '#':return self.f2(self.v, min(self.r, r) - max(self.l, l))midh = self.mid_hanss = []if l < midh:anss.append(self.left.query(l, r))if r > midh:anss.append(self.right.query(l, r))return reduce(self.f1,anss)MAX=10**9
class MyCalendarThree:def __init__(self):#线段最大值:f1=lambda a,b:max(a,b)f2=lambda a,n:aself.seg = SegTree(f1,f2,0,MAX,0)def book(self, start: int, end: int) -> int:self.seg.inc_seg(start,end,1)return self.seg.query(0,MAX)# Your MyCalendarThree object will be instantiated and called as such:
# obj = MyCalendarThree()
# param_1 = obj.book(start,end)
最强py线段树区间修改 + 区间查询模板整理
坑点
如果发现先查后加不大行
可以先加后查再减
我觉得这是由于lazy tag的代码导致的lazy问题
MyCalendarTwo详见
因为动态开店先查的话可能某些点不存在
所以要使用“先加-后查-先加”的写法
20220820总结
inc_seg + 单点查询慎用,很可能不行(因为lazy tag)
cover_set + 单点查询可能可以(天际线问题)
python:线段树区间修改 + 区间查询 模板 + 坑点总结相关推荐
- HDU 1698 Just a Hook (线段树区间修改+区间查询)
题目链接: 传送门 题意:Pudge对装备钩子进行若干次的强化,强化分为三种分别对应的价值是1,2,3,在经历过若干次操作后,输出钩子对应的总价值,每次强化都是对钩子进行区间修改 解题思路:在明白了题 ...
- tzoj3315 买火车票(线段树+区间修改+区间查询)
时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte 描述 Byteotian州铁道部决定赶上时代,为此他们引进了城市联网.假设城市联网顺次连接着n 个市从1 ...
- 【模板】线段树区间修改
区间修改: 区间修改过程类似于区间询问,例如将[ul, ur]内的所有元素都加上v,则进行如下操作: 当当前区间被区间[ul, ur]所包含时, 当前的节点值加上区间长度(r - l + 1)乘以v ...
- hdu1698(线段树/区间修改/求和)
hdu1698"Just a Hook" 题意: 有一个区间s [1,n],每一节si的初始价值为1.定义操作:x y val,将区间[x,y]中的每一个小节的价值改为val.问: ...
- poj3468 线段树区间更新+区间查询
题目链接: http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS Memory Limi ...
- POJ 2777 Count Color (线段树区间修改 + 状态压缩)
题目链接:POJ 2777 Count Color [题目大意] 给你 n 块板子, 编号1--n , 板子的颜色最多30种, 初始时 板子的颜色都是 1: 有两种操作 1 .把给定区间的板子染成一 ...
- 1631 小鲨鱼在51nod小学(线段树区间修改+单点查询:不用下传lazy的区间修改)
题目描述: 1631 小鲨鱼在51nod小学 鲨鱼巨巨2.0(以下简称小鲨鱼)以优异的成绩考入了51nod小学.并依靠算法方面的特长,在班里担任了许多职务. 每一个职务都有一个起始时间A和结束时间B, ...
- codeforces:E2. Array and Segments (Hard version)【线段树 + 区间修改】
分析 思路很简单 遍历每个作为最大值,然后区间不包含当前最大值的都可以减掉 easy version就可以这样暴力解决 然后求出最大差值 暴力解法 import sys input = sys.std ...
- UVa 11992 (线段树 区间修改) Fast Matrix Operations
比较综合的一道题目. 二维的线段树,支持区间的add和set操作,然后询问子矩阵的sum,min,max 写完这道题也是醉醉哒,代码仓库里还有一份代码就是在query的过程中也pushdown向下传递 ...
最新文章
- “AV终结者/8749”病毒清理办法
- Java学习小程序(9)冒泡排序算法实现
- 【Liunx】Linux vi/vim 教程
- 弱鸡儿终于没爆零Day7
- mysql8 groups关键字
- ITIL 4 Foundation知识体系-第一章-介绍
- 利用ABBYY Screenshot Reader快速截取网页并识别文本
- Adapter与AdapterView
- 5G网络规划面临的挑战
- android多点触控参数,转 android 下的webview 设置多点触控放大
- 整理了18个可以免费学习编程的网站
- 二进制数的加法步骤解析
- coreldraw快速撤回_CorelDRAW基础教程,教你CDR X8撤销、重做与重复操作方法
- 解密微信电脑版image文件夹下缓存的用户图片
- 如何防止失眠——学习笔记
- 龙芯2k开发板Debian系统安装教程
- React 18的基本使用
- 电脑CPU占用率100%如何处理 电脑CPU占用率100%解决方法
- 考研复试英语自我介绍模板
- 工业控制领域电子元件国产化硬件设计替代解读