首页 > 其他分享 >暑期竞赛培训 Day 11—— < 树状数组 >

暑期竞赛培训 Day 11—— < 树状数组 >

时间:2023-07-30 17:25:27浏览次数:40  
标签:11 树状 int lowbit sum 暑期 数组 区间 Day

本文大部分内容来自教练的博客 [https://www.cnblogs.com/hbhszxyb/]。

树状数组

一、适用范围:

树状数组是一个查询和修改复杂度都为 log(n)的数据结构,常常用于查询任意区间的所有元素之和。与前缀和的区别是支持动态修改, log(n)的时间进行修改,log(n)查询。

支持如下操作:

  • [1] 单点修改区间查询
  • [2] 区间修改单点查询
  • [3] 区间修改区间查询

二、算法原理

1.树状数组较好的利用了二进制。它的每个节点的值代表的是自己前面一些连续元素的和。至于到底是前面哪些元素,这就由这个节点的下标决定。

2.设节点的编号为 i,那么:

所以:

C[1] = A[1] // lowbit(1)个元素之和
C[2] = C[1] + A[2] = A[1] + A[2] // lowbit(2)个元素之和
C[3] = A[3] // lowbit(3)个元素之和
C[4] = C[2] + C[3] +A[4] = A[1] + A[2] + A[3] +
A[4] // lowbit(4)个元素之和
C[5] = A[5]
C[6] = C[5] + A[6] = A[5] + A[6]
C[7] = A[7]
C[8] = C[4] + C[6] + C[7] + A[8] = A[1] + A[2] +A[3] + A[4] + A[5] + A[6] + A[7] + A[8]

显然前缀和可以通过区间和求解出来:

sum[1] = c[1]
sum[2] = c[2]
sum[3] = c[3] + c[2]
sum[4] = c[4]
sum[5] = c[5] + c[4]
sum[6] = c[6] + c[4]
sum[7] = c[7] + c[6] + c[4]
sum[8] = c[8]
例如求解sum[7] 见下图:

我们发现:

7 - lowbit(7) = 6
6 - lowbit(6) = 4
4 - lowbit(4) = 0
sum[7] = c[7] + c[6] + c[4]

所以当我们维护出 c 数组,则我们可以通过循环不停的减
lowbit 直到为 0 计算出前缀和。

前缀和代码实现

int get_sum(int i){
	int res=0;
	for(;i;i-=lowbit(i))
		res+=c[i];
	return res;
}

点更新

当我们需要对原始序列的某个元素 a[i] 更新成 a[i]+x 时,我们只
需把树状数组中包含了 a[i] 的区间数组 c[i] 进行即可。

如图,如果 a[3] 进行了更新,包含了 a[3] 的区间只有
c[3]c[4],c[8] 我们只需更新这三个区间即可。如何遍历这三个区间呢?我们发现:
3 + lowibt(3) = 4
4 + lowbit(4) = 8
我们可以通过循环不停的加 lowbit 直到大于 n ,对相应的
区间进行更新即可。

向上更新代码实现:

void Update(int i,int x){
	for(;i<=n;i+=lowbit(i))
		c[i]+=x;
}

——————————————华丽的分割线QWQ

三、 实际应用:

了解了这么多
那么我们就来看道简单题吧(我目前唯一能看懂的一道题QWQ)

题目描述:

单点修改区间求和

如题,已知一个数列,你需要进行下面两种操作:
将某一个数加上 x
求出某区间每一个数的和

输入格式

第一行包含两个正整数 n,m,分别表示该数列数字的个数和操作的总个数。
第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项初始值。
接下来 m 行每行包含 3 个整数,表示一个操作,具体如下:
1 x k 含义:将第 x 个数加上 k
2 x y 含义:输出区间 [x,y] 内每个数的和

输出格式

输出包含若干行整数,即为所有操作 2 的结果
样例输入
5 5
1 5 4 2 3
1 1 3
2 2 5
1 3 -1
1 4 2
2 1 4
样例输出
14
16

解题步骤:

根据刚才前缀和与向上更新的基础,现在只需要用一个一个求 sum[x] 与 sum[y] 的值就行了,另外,题目意思是求 x —— y 的区间和,那么 sum[x]就要变成 sum[x-1] ,这样就完成啦!!!(再码就寄了QWQ)

代码实现:

#include<bits/stdc++.h>
using namespace std;	
const int maxn=5e5+5;
int n,m;
int c[maxn];
int lowbit(int x){
	return x&(-x);
}
void Update(int i,int x){
	for(;i<=n;i+=lowbit(i))
		c[i]+=x;
}
int get_sum(int i){
	int res=0;
	for(;i;i=i-lowbit(i))
		res+=c[i];
	return res;
}
void sol(){	
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		int x;
		scanf("%d",&x);
		Update(i,x);
	}
	while(m--){
		int op,x,y;
		scanf("%d%d%d",&op,&x,&y);
		if(op==1) Update(x,y);
		else printf("%d\n",get_sum(y)-get_sum(x-1));
	}
}
int main(){
	sol();
	return 0;
}

O得K(完美的结束)QWQ————————————

标签:11,树状,int,lowbit,sum,暑期,数组,区间,Day
From: https://www.cnblogs.com/Wanghaoran-20080414/p/17591707.html

相关文章

  • 集训Day 7
            比赛开始看了看T1veryGood有思路,直接用手动全排列A掉(虽然卡了5min左右但get100pt),转过来看T2用暴力模拟A掉(get100pt),接着看T3虽然第一眼因为最大值最小看成了二分,但很快否决了,这指定是一道多源最短路,但是当时脑子亿抽写了一个适用于单源最短路的......
  • 每日总结(补档7月11日)
    今天是我们要去旅游的第一天,从草原到新疆,想想就觉得让人兴奋,除了一些必要的用品外,我还带了大道至简,无他,不带去看不完了,这知识的重量压了我一路,从我们区区政府上车,6个小时的车程属实是难为人。ps:旅游这些天带不了电脑,手机又发不了博,只能回来一块写,望老师见谅。......
  • ChatIE:通过多轮问答问题实现实命名实体识别和关系事件的零样本信息抽取,并在NYT11-HRL
    ChatIE:通过多轮问答问题实现实命名实体识别和关系事件的零样本信息抽取,并在NYT11-HRL等数据集上超过了全监督模型零样本信息抽取(InformationExtraction,IE)旨在从无标注文本中建立IE系统,因为很少涉及人为干预,该问题非常具有挑战性。但零样本IE不再需要标注数据时耗费的时间和人力,因......
  • 7.30 day7字符串
    60+10+100+0=170连续2天没写出来简单题了,不过我的字符串是真的弱,趁着这次复习一下T1倒序考虑即可T2之前模拟赛里有,但是只记得做过不记得做法了定义一个字符串的本质是\(A_x=x-pre(A_x)\)\(pre(x)\)指上一次出现\(x\)的位置,如果是第一个字符则是0两个字符串相等的条件是本......
  • 11_Spring_AOP概念和原理
    11_Spring_AOP概念和原理AOP切面编程一般可以帮助我们在不修改现有代码的情况下,对程序的功能进行拓展,往往用于实现日志处理,权限控制,性能检测,事务控制等AOP实现的原理就是动态代理,在有接口的情况下,使用JDK动态代理,在没有接口的情况下使用cglib动态代理为Dao层所有的......
  • 最完美WIN11_Pro_22H2.22621.2070软件选装纯净版VIP51.2
    【系统简介】=============================================================1.本次更新母盘来自UUP_WIN11_Pro_22H2.22621.2070。进一步精简优化调整。2.只为呈现最好的作品,手工精简优化部分较多。3.OS版本号为22621.2070。个别要求高的就下MSDN吧,里面啥功能都有。4.集成《DrvCeo......
  • Day09_列表类型
    1.list()类型转换用法和作用: 2.列表操作:正向取值、反向去之、可取也可以改、索引不存在则报错: 3.列表操作:列表追加值: 4.列表操作:列表插入值: 5.列表操作:extend用法两个列表元素合并、字符串合并到列表中: 6.列表操作:列表删除方式一del: 7.列表操作:列表删除方......
  • 《Kali渗透基础》11. 无线渗透(一)
    @目录1:无线技术特点2:IEEE802.11标准2.1:无线网络分层2.2:IEEE2.3:日常使用标准2.3.1:802.112.3.2:802.11b2.3.3:802.11a2.3.4:802.11g2.3.5:802.11n3:无线网络运行模式3.1:Infrastructure3.2:AD-HOC3.3:WDS3.4:MonitorMode4:无线技术概念4.1:信号单位4.2:全向天线4.3:定向天线本系列侧重方法......
  • DAY8
    函数指针使用案例(回调函数)代码:#include<stdio.h>voidA(){printf("Hello");}voidB(void(*ptr)())//B函数有一个函数指针作为它的参数{//ptr指向一个函数,这个函数应该是不带参数的而且返回void,就像A那样ptr();//使用函数指针ptr调用......
  • 常见的状态码 11
    状态码   短语   描述100   Continue   服务端已收到请求并要求客户端继续发送主体200   Ok   已成功提交,且响应主体中包含请求结果201   Created   PUT请求方法的返回状态,请求成功提交301   MovedPermanently   请求永久重定向302  ......