当前位置: 首页 > wzjs >正文

微信免费做邀请函模版网站哈尔滨优化网站公司

微信免费做邀请函模版网站,哈尔滨优化网站公司,分销网站建设方案,网站建设实训课指导书网站版式分析目录 区间乘 场景1.整数模运算 场景2.浮点数运算 #131. 树状数组 2 :区间修改,单点查询 #132. 树状数组 3 :区间修改,区间查询 树状数组底层逻辑探讨 / 模版代码-P3374-P3368-CSDN博客 在上一章最后我略带了原本只能单点操作…

目录

区间乘

场景1.整数模运算

场景2.浮点数运算

#131. 树状数组 2 :区间修改,单点查询

#132. 树状数组 3 :区间修改,区间查询


树状数组底层逻辑探讨 / 模版代码-P3374-P3368-CSDN博客

在上一章最后我略带了原本只能单点操作的树状数组通过前缀和和差分实现了区间加

模板代码如下(以模板题P3368为例)

def lowbit(x):return x & -xdef init(a, tree1, tree2, n): #从数组a初始化d数组和d*i数组for i in range(1, n + 1):delta = a[i] - a[i - 1]add(tree1, n, i, delta)add(tree2, n, i, delta * (i - 1))def add(tree, n, x, v):  #树状数组单点操作while x <= n:tree[x] += vx += lowbit(x)def query(tree, x):  #树状数组区间查询(前缀和)#可用于d数组前缀和实现数组a的单点查询res = 0while x > 0:res += tree[x]x -= lowbit(x)return resdef range_add(tree1, tree2, n, l, r, v):  #区间操作add(tree1, n, l, v)             #操作1add(tree1, n, r + 1, -v)add(tree2, n, l, v * (l - 1))   #操作2add(tree2, n, r + 1, -v * r)def prefix_sum(tree1, tree2, x):    #数组a从1到x区间的前缀和return query(tree1, x) * x - query(tree2, x)def range_sum(tree1, tree2, l, r):  #数组a从l到r区间的和return prefix_sum(tree1, tree2, r) - prefix_sum(tree1, tree2, l - 1)n,m=map(int,input().split())a=[0]+list(map(int,input().split())) #下标从1开始t1=[0]*(n+2)
t2=[0]*(n+2)
init(a,t1,t2,n)for _ in range(m):te=tuple(map(int,input().split()))#用tuple方便解包if te[0]==1:  #区间加l,r,v=te[1:]range_add(t1,t2,n,l,r,v)else:idx=te[1]val=query(t1,idx) #数组d前缀和实现数组a单点查询print(val)

区间乘

和“通过前缀和实现区间和”类似,我们需要计算前缀乘积从而实现区间乘

def lowbit(x):return x & -xdef multiply_update(tree, n, x, v):  # 树状数组单点乘操作while x <= n:tree[x] *= vx += lowbit(x)def multiply_query(tree, x):  # 树状数组前缀乘积查询res = 1while x > 0:res *= tree[x]x -= lowbit(x)return resdef init(a, tree, n):  # 初始化 f 数组,令 f[1] = a[1], f[i] = a[i] / a[i-1] (i>=2)# 树状数组 tree 下标 1~n 均初始化为 1for i in range(1, n + 1):tree[i] = 1for i in range(1, n + 1):if i == 1:factor = a[1]else:factor = a[i] / a[i - 1]multiply_update(tree, n, i, factor)def range_multiply(tree, n, l, r, v):  # 区间乘法更新:区间 [l, r] 的元素均乘 vmultiply_update(tree, n, l, v)       # f[l] 乘以 vif r + 1 <= n:multiply_update(tree, n, r + 1, 1 / v)  # f[r+1] 乘以 1/vdef prefix_product(tree, x):  # 数组 a 从 1 到 x 的前缀乘积return multiply_query(tree, x)def range_product(tree, l, r):  # 区间 [l, r] 的乘积return prefix_product(tree, r) / prefix_product(tree, l - 1)

场景1.整数模运算

在数据较大、有溢出风险的情况下,我们通常选择模一个质数(例如 MOD = 10⁹+7),并用乘法逆元实现区间乘操作:

MOD = 10**9 + 7def lowbit(x):return x & -xdef modinv(x):return pow(x, MOD - 2, MOD)def multiply_update(tree, n, x, v):# 模运算下,更新 BIT 内元素:乘上 v (模 MOD)while x <= n:tree[x] = (tree[x] * v) % MODx += lowbit(x)def multiply_query(tree, x):res = 1while x > 0:res = (res * tree[x]) % MODx -= lowbit(x)return resdef init(a, tree, n):# 将树状数组初始化为乘法单位元1for i in range(1, n + 1):tree[i] = 1for i in range(1, n + 1):if i == 1:factor = a[1] % MODelse:# 计算相邻比值: a[i] / a[i-1] 变为 a[i] * modinv(a[i-1])factor = (a[i] * modinv(a[i-1])) % MODmultiply_update(tree, n, i, factor)def range_multiply(tree, n, l, r, v):# 区间 [l, r] 同时乘上 vmultiply_update(tree, n, l, v % MOD)if r + 1 <= n:multiply_update(tree, n, r + 1, modinv(v % MOD))def prefix_product(tree, x):return multiply_query(tree, x)def range_product(tree, l, r):# 区间乘积为前缀乘积之比return (prefix_product(tree, r) * modinv(prefix_product(tree, l - 1))) % MOD

场景2.浮点数运算

浮点版本直接使用除法操作

def lowbit(x):return x & -xdef multiply_update(tree, n, x, v):while x <= n:tree[x] *= vx += lowbit(x)def multiply_query(tree, x):res = 1.0while x > 0:res *= tree[x]x -= lowbit(x)return resdef init(a, tree, n):for i in range(1, n + 1):tree[i] = 1.0for i in range(1, n + 1):if i == 1:factor = a[1]else:# 浮点除法直接计算相邻比值factor = a[i] / a[i - 1]multiply_update(tree, n, i, factor)def range_multiply(tree, n, l, r, v):multiply_update(tree, n, l, v)if r + 1 <= n:multiply_update(tree, n, r + 1, 1.0 / v)def prefix_product(tree, x):return multiply_query(tree, x)def range_product(tree, l, r):return prefix_product(tree, r) / prefix_product(tree, l - 1)

下面我们还是做几道题(但是由于用树状数组实现区间乘积的题目较少,一般都用线段树,所以我们还是先看看区间和的题目) 

#131. 树状数组 2 :区间修改,单点查询

https://loj.ac/p/131

这道题和P3368一个套路,直接套我文章开头的代码即可

#132. 树状数组 3 :区间修改,区间查询

https://loj.ac/p/132

改模板代码中的query区间查询函数为range_sum函数即可

def lowbit(x):return x & -xdef init(a, tree1, tree2, n): #从数组a初始化d数组和d*i数组for i in range(1, n + 1):delta = a[i] - a[i - 1]add(tree1, n, i, delta)add(tree2, n, i, delta * (i - 1))def add(tree, n, x, v):  #树状数组单点操作while x <= n:tree[x] += vx += lowbit(x)def query(tree, x):  #树状数组从1到x区间的前缀和查询res = 0while x > 0:res += tree[x]x -= lowbit(x)return resdef range_add(tree1, tree2, n, l, r, v):  #区间操作add(tree1, n, l, v)             #操作1add(tree1, n, r + 1, -v)add(tree2, n, l, v * (l - 1))   #操作2add(tree2, n, r + 1, -v * r)def prefix_sum(tree1, tree2, x):    #数组a从1到x区间的前缀和return query(tree1, x) * x - query(tree2, x)def range_sum(tree1, tree2, l, r):  #数组a从l到r区间的和return prefix_sum(tree1, tree2, r) - prefix_sum(tree1, tree2, l - 1)n,m=map(int,input().split())
'''
a=[0]+list(map(int,input().split())) #下标从1开始
'''
t1=[0]*(n+2)
t2=[0]*(n+2)
'''
init(a,t1,t2,n)
'''
for _ in range(m):te=tuple(map(int,input().split()))#用tuple方便解包if te[0]==1:l,r,v=te[1:]range_add(t1,t2,n,l,r,v)else:l,r=te[1:]val=range_sum(t1,t2,l,r)print(val)

http://www.dtcms.com/wzjs/144827.html

相关文章:

  • 安徽省建设厅官方网站建委窗口seo排名优化表格工具
  • 做网站用多大的服务器外贸营销系统
  • 廊坊建设网站的公司百度文库官网首页
  • 中文网站 可以做谷歌推广吗谷歌外贸平台推广需要多少钱
  • 注册城乡规划师通过率seo搜索引擎优化论文
  • 文明网站建设管理培训心得资讯门户类网站有哪些
  • 单页面网站怎么做的网络营销的核心
  • 淘宝客app开发seo入门教程seo入门
  • 佛山网上房地产长春网站优化页面
  • 如何申请网页域名上海外贸网站seo
  • 66公里智慧门店管理系统谷歌seo视频教程
  • 硬件工程师培训班靠谱吗百度seo优化及推广
  • 渭南网站建设seo网络营销比较常用的营销模式
  • 网站建设与网页设计作业深圳网络推广外包
  • 企业咨询合同做优化关键词
  • 做网站销售的换工作惠州seo
  • 网站设计建设公司教程唐老鸭微信营销软件
  • 京东网站建设目的网络营销师证书需要多少钱
  • 新版织梦腾讯3366小游戏门户网站模板源码怎么做电商平台
  • 苏ICP备网站建设中企动力无锡seo关键词使用
  • wordpress的文章收藏seo经理
  • 自己做的网站怎么让别人访问市场营销证书含金量
  • 网站建设免费模板怎么创作自己的网站
  • 党建网站 自身建设单页网站怎么优化
  • wap网站开发用什么语言最新国际新闻头条新闻
  • 如何域名解析网站建设永久免费二级域名申请
  • 做语音聊天网站要多少钱近一周新闻热点事件
  • 深圳网站建设开发网络推广收费价目表
  • 网站用户体验解决方案关联词有哪些三年级
  • 网站建设费用要求百度推广广告收费标准