树状数组 小白篇(2)暨区间修改

这篇主要来讲一讲树状数组的区间修改

因为一个一个点改,毫无疑问耗时太长

所以,机智的人类YY出了用差分来表示数组

为了便于理解,简单一点数组{an}:a[1]=0, a[2]=0, a[3]=0, a[4]=0, a[5]=0, a[6]=0 ,a[7]=0, a[8]=0, a[9]=0

用差分思想,delta[x]表示a[x]-a[x-1]

显然,一开始delta[]=0

我们先计算出前n项和{sn}来

然后别眨眼,下面就是见证奇迹的时刻!

有个分界线显得正式一点



我们要把a[3]到a[6]整段提高3个单位长度,就让delta[3]+=3, delta[7]-=3

想象成阶梯,一端抬起,另一端就压下去。(自行脑补)

那么现在的a[x]+=delta[1]+delta[2]+……+delta[x-1]+delta[x]

我现在要得到前7项的和,s[7]+=每一项应该加的差分

          暨s[7]+=(delta[1])+(delta[1]+delta[2])+(delta[1])+delta[2]+delta[3])+……+(delta[1]+delta[2]+delta[3]+delta[4]+delta[5]+delta[6]+delta[7])

我还是画个图吧(为了方便说明只画差分的)

显然搬过砖的都知道,这个砖不好搬,因为它不方

那我们就把它变方来

(为什么那么丑,因为我不会画画以及懒)

额妹子!现在就好表示这堆砖了!!!!!!!!!

(7+1)(∑delta【1~7】)-(delta【1】*1+delta【2】*2+……+delta【7】*7)

后面的delta【n】*n很难看是不是?

那就表示成deltai【】

定义deltai【i】=delta【i】*i

显然因为要大量求和,所以我们把deltai和delta维护成树状数组

那么

1 // 修改:把[l, r]区间均加上x
2 Update(delta, l, x);
3 Update(delta, r+1, -x);
4 Update(deltai, l, x * l);
5 Update(deltai, r+1, -x * (r+1));
6 //updata相当于上一篇的add
// 查询:[l, r]区间和
long long suml = s[l - 1] + l * Query(delta, l - 1) - Query(deltai, l - 1);
long long sumr = s[r] + (r + 1) * Query(delta, r) - Query(deltai, r);
ans=sumr - suml;
//query相当于上一篇的sum

是不是很神奇?

感谢

“每天心塞一点点”的博客(我喜欢这个名字)

参考博文地址

时间: 2024-08-29 18:30:08

树状数组 小白篇(2)暨区间修改的相关文章

树状数组 小白篇(1)

身为一名弱省oier中的mengbier,简单讲一下我是怎么学会基础的树状数组的 不算华丽的分割线 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构. 其发明者命名为Fenwick树,最早由Peter M. Fenwick于1994年以<A New Data Structure for Cumulative Frequency Tables>为题发表在 "SOFTWARE PRACTICE A

洛谷 P3368 【模板】树状数组 2 如题(区间修改+单点查询)

P3368 [模板]树状数组 2 时空限制1s / 128MB 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含2或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x 含义:输出

P3368 【模板】树状数组 2 单点查询与区间修改

题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含2或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x 含义:输出第x个数的值 输出格式: 输出包含若干行整数,即为所有操作2的结

树状数组入门篇2

树状数组的高效性主要就是通过将一条线段分成若干个小线段(其中每个小线段存储着2^k大小的区间和,这就将区间和问题复杂度降到了logn),而不是一个一个单一的点 add()操作修改了单点的值,同时对之后的父亲节点进行了更新(之所以只更新该点以及该点的父亲节点而不更新该点的非父亲节点,是因为求和时父亲节点直接包含该点所以会跳过该点,也就不能接受该点,所以就需要自身更新,而非父亲节点在求和时会直接加上该点,所以就不需要进行更新) 正是由于add()操作对父亲节点以及非父亲节点的区别才使每次的sum()

洛谷 P3374 【模板】树状数组 1 如题(单点修改+区间查询)

P3374 [模板]树状数组 1 时空限制1s / 128MB 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x k 含义:将第x个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内

BZOJ 1103 大都市(dfs序+树状数组)

应该是一道很水的题吧... 显然可以用树链剖分解决这个问题,虽然不知道多一个log会不会T.但是由于问题的特殊性. 每次修改都是将边权为1的边修改为0,且询问的是点i到根节点的路径长度. 令点i到根节点的路径长度为w[i],显然初始时w[i]=dep[i].考虑修改边为(u,v),那么令u为深度大的点. 那么u的子树的所有答案就要减1.考虑dfs序,则每次需要修改的是一段连续的区间. 树状数组维护单点查询,区间修改,美滋滋. # include <cstdio> # include <c

【不可能的任务13/200】bzoj2743离线+树状数组

奇葩染色,对于每一个点关心的是前前个同颜色的位置,但是处理方法相同 离线比较神奇,按照右端点排序,然后每次用的是左端点,就不用建可持久化树状数组(什么鬼)了 区间修改+单点查询 果断差分以后用树状数组 1 #include <cstdio> 2 #include <algorithm> 3 struct que 4 { 5 int l,r,id; 6 } q[1000001]; 7 bool operator<(que a,que b){return a.r<b.r;}

数据结构——树状数组

我们今天来讲一个应用比较广泛的数据结构——树状数组 它可以在O(nlogn)的复杂度下进行单点修改区间查询,下面我会分成三个模块对树状数组进行详细的解说,分别是树状数组基本操作.树状数组区间修改单点查询的实现.树状数组查询最值的实现 一. 树状数组一般分为三种操作,初始化.修改.查询 在讲基本操作之前,我们先来看一张图 这张图就是树状数组的存储方式,对于没有接触过树状数组的人来说看懂上面这张图可能有些困难,上图的A数组就是我们的原数组,C数组则是我们需要维护的数组,这样存储能干什么呢,比如我们在

【算法#3】树状数组&amp;二叉索引树

其实是数据结构. 智推连续几天给我推树状数组的模板,还放在第一位-- 对着蓝书的图看了好几天才看懂,树状数组的另外一个名字是二叉索引树,指通过把一个数组抽象的变形成树状的以求得到树形数据结构的效果.有人说是线段树的阉割版,我不太清楚,树状数组应该是不支持区间修改加速的. 首先我们需要理解lowbit的概念,它指的是一个数转成二进制后位数最低的那个1表示的值.它具有一个特殊的性质但是为什么具有这个性质是无须证明也不用了解的. 然后我们画一个图,在一定范围内按lowbit的大小从上向下逐层分布,一层