【JZYZ7.6日集训】树状数组进阶/二维偏序/二维数点/线段树上二分/转离线普通平衡树

这篇博客详细介绍了树状数组的进阶应用,包括一维和多维树状数组的单点修改和区间查询,二维偏序问题,二维数点问题,以及树状数组在二分查找中的应用。通过实例和具体算法讲解,帮助读者深入理解树状数组在解决复杂问题中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

7.6集训Day1 树状数组进阶

今天的集训怎么说,算是来了个下马威吧~~(虽然我暂时还没去听课)~~。

但是看着zyz大佬找的五道题和一道自己出的题,最低也是个蓝色的,最高的没有评级,但我觉得这道题可以评黑(ICPC 2018 WF的Triangles)。多少有点害怕了属于是。

废话少说,来开始今天的学习总结。

【复习】基础的树状数组知识!

性质:任意正整数关于2的不重复次幂的唯一分解性质,[1,x][1,x][1,x]区间可以被分成O(logx)O(logx)O(logx)个小区间。

这些子区间的共同特点是:若区间结尾为RRR,则区间长度就等于RRR的“二进制分解”下的最小的222次幂,设为lowbit(R)lowbit(R)lowbit(R)

对于给定的序列AAA,建立一个数组ccc,其中c[x]c[x]c[x]保存AAA的区间[x−lowbit(x)+1,x][x-lowbit(x)+1,x][xlowbit(x)+1,x]中所有数的和。

该结构满足以下性质:

(1)每个内部结点c[x]c[x]c[x]保存以它为根的子树中所有叶结点的和。

(2)每个内部结点c[x]c[x]c[x]的子节点个数等于lowbit(x)lowbit(x)lowbit(x)的大小。

(3)除了树根之外,每个内部结点c[x]c[x]c[x]的父节点是c[x+lowbit(x)]c[x+lowbit(x)]c[x+lowbit(x)]

(4)树的深度是O(logN)O(logN)O(logN)

树状数组一个很有意思的点是初始化。假设源数组与树状数组初始均为零,则树状数组就是通过依次调用add(i,A[i])add(i,A[i])add(i,A[i])来实现的。
同时,其实不需要专门保存源数组,因为所有源数组的操作与查询全部都映射到了树状数组上,即所有需要用到的信息树状数组都有保存,无需额外再保存源数组。在很多数据结构中都是这样的情况,源数据结构其实不用保存。

一维树状数组:

单点修改单点查询
#define lowbit(x) x&-x
void add(int x,int y){
	for(;x <= N;x += lowbit(x)) c[x] += y;
}
int ask(int x){
	int ans = 0;
	for(;x;x -= lowbit(x)) ans += c[x];
	return ans;
}
//查询前缀和:sum(y)-sum(x-1)
区间修改单点查询

考虑源数组AAA,令前缀和数组为S,有Si=ΣAiS_i=\Sigma{A_i}Si=ΣAi。反过来称AAASSS的差分数组。即,如果令AAA为源数组,则其差分数组DDD为:

? ?D1=A1?Di=Ai−Ai−1?\begin{array}{c} ? D_{1}=A_{1} \\ ? D_{i}=A_{i}-A_{i-1} ? \end{array}?D1=A1?Di=AiAi1?

如果针对差分数组D建立一个树状数组,就可以在logloglog时间内完成DDD上的单点操作,也就相当于可以在logloglog时间内完成源数组的区间修改操作。不过因为此时树状数组求的是差分数组的前缀和,实际上就是AAA中某个元素的值,所以,此时树状数组支持的是区间修改、单点查询。

int c[N+5]; //c[i] = a[i] - a[i-1]
void add(int x,int y){
   
   
    for(;x <= N;x += lowbit(x)) c[x] += y;
}
void add_range(int l,int r,int v){
   
   
    add(l,v);add(r+1,-v);
}
int ask(int x){
   
   
    int sum = 0; 
    for(;x > 0; x -= lowbit(x)) sum += c[x];
    return sum;
}
区间修改区间查询

开一个bbb数组,起初全为0

我们用树状数组维护bbb数组,对于每条ADD  l  r  dADD~~l~~r~~dADD  l  r  d的指令,把b[l]+=db[l]+=db[l]+=d,再把b[r+1]−=db[r+1]-=db[r+1]=d

我们已经知道,bbb数组的前缀和Σi=1xb[i]\Sigma^{x}_{i=1}b[i]Σi=1xb[i]就是经过这些指令后a[x]a[x]a[x]增加的值。

aaa的前缀和a[1∼x]a[1\sim x]a[1x]增加的值就是Σi=1xΣj=1ib[j]\Sigma^{x}_{i=1} \Sigma^{i}_{j=1} b[j]Σi=1xΣj=1ib[j]

展开得:Σi=1xΣj=1ib[j]=Σi=1x(x−i+1)∗b[i]=(x+1)Σi=1xb[i]−Σi=1xi∗b[i]\Sigma^{x}_{i=1} \Sigma^{i}_{j=1} b[j]=\Sigma^{x}_{i=1}(x-i+1)*b[i]=(x+1)\Sigma^{x}_{i=1}b[i]-\Sigma^{x}_{i=1}i*b[i]Σi=1xΣj=1ib[j]=Σi=1x(xi+1)b[i]=(x+1)Σi=1xb[i]Σi=1xib[i]

增加一个树状数组,用于维护i∗b[i]i*b[i]ib[i]上的前缀和Σi=1xi∗b[i]\Sigma^{x}_{i=1}i*b[i]Σi=1xib[i]。则可以直接计算上式

则有以下四个操作

(1)C0C_0C0:在lll上的数加ddd (2)C0C_0C0:在r+1r+1r+1上的数减ddd
(3)C1C_1C1:在lll上的数加l∗dl*dld(4)C1C_1C1:在r+1r+1r+1上的数减(r+1)∗d(r+1)*d(r+1)d

另外建立数组sumsumsum存储aaa的原始前缀和,对于每条指令Ask  l  rAsk~~l~~rAsk  l  r,拆成1∼r1\sim r1r1∼l−11 \sim l-11l1两个部分,二者相减

(sum[r]+(r+1)∗ask(c0,r)−ask(c1,r))−(sum[l−1]+l∗ask(c0,l−1)−ask(c1,l−1))(sum[r]+(r+1)*ask(c_0,r)-ask(c_1,r))-(sum[l-1]+l*ask(c_0,l-1)-ask(c_1,l-1))(sum[r]+(r+1)ask(c0,r)ask(c1,r))(sum[l1

数据库连接失败spring: datasource: type: com.alibaba.druid.pool.DruidDataSource # driverClassName: org.mariadb.jdbc.Driver driverClassName: com.mysql.cj.jdbc.Driver druid: # 主库数据源 master: #test # url: jdbc:mysql://59.110.60.119:3306/WaterQuality # username: mydb # password: 123456 #production # url: jdbc:mysql://114.116.210.210:9527/water_jzyz # username: waterjzyz # password: waterjzyz@890 #使用本地的 # url: jdbc:mysql://8.142.164.112:3306/water_jzyz # username: root # password: root url: jdbc:mysql://localhost:3307/waterquality username: root password: root # # 从库数据源 slave: # 从数据源开关/默认关闭 enabled: false url: username: password: # 初始连接数 initialSize: 5 # 最小连接池数量 minIdle: 10 # 最大连接池数量 maxActive: 20 # 配置获取连接等待超时的时间 maxWait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 # 配置一个连接在池中最大生存的时间,单位是毫秒 maxEvictableIdleTimeMillis: 900000 # 配置检测连接是否有效 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false webStatFilter: enabled: true statViewServlet: enabled: true # 设置白名单,不填则允许所有访问 allow: url-pattern: /druid/* # 控制台管理用户名和密码 login-username: dllcsoft login-password: dllcsoft filter: stat: enabled: true # 慢SQL记录 log-slow-sql: true slow-sql-millis: 1000 merge-sql: true wall: config: multi-statement-allow: true
最新发布
07-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值