首页 > 其他分享 >树状数组学习笔记

树状数组学习笔记

时间:2023-08-08 18:00:23浏览次数:54  
标签:ch limits 树状 int sum 笔记 times 数组

树状数组作为一个常数小且好写的数据结构,虽然功能没有线段树那么齐全,但是其中的扩展内容还是很多的。

维护区间和

1.0 BIT 的作用

树状数组可以做到单次 logn 求前缀和,单次 logn 修改信息维护一个前缀和。

1.1 区间修改 单点查询

考虑维护差分数组 \(c[i]=a[i]-a[i-1]\) 。

在查询的部分,一个点的值 \(a[i]\) 将等于 \(\sum\limits_{j=1}^i{c[j]}\) 的值,也就是求前缀和。

修改的话,由于我们要维护的是前缀和,对于一个差分数组来说,显然等价于给 \(l\) 上的点加上 \(v\) , 给 \(r+1\) 上的点加上 \(-v\)。

1.2 区间修改 区间查询

这个部分需要使用两个 BIT 去维护了,设 \(r\) 表示右端点。

首先,由于加法满足结合率,所以可以将区间转化为两端点前缀和之差。

单点的值仍然满足 \(a[i]=\sum\limits_{j=1}^i{c[j]}\) ,因为要求 \(\sum{a[i]}\) ,所以原式子可以写为 \(\sum\limits_{i=1}^r\sum\limits_{j=1}^i{c[j]}\) 。

观察这个式子,不难发现每个 \(c[j]\) 出现了 \(r-j+1\) 次,则原式子又可以写成 \(\sum\limits_{i=1}^rc[i]\times(r+1)-\sum\limits_{i=1}^rc[i]\times i\) 。

因此我们需要开两个 BIT 去单独维护 \(c[i]\) 和 \(c[i]\times i\) 。

第一个好维护,第二个就将 \(l\) 上的点加上 \(v\times l\) , 给 \(r+1\) 上的点加上 \(-v\times(r+1)\) 。

这里给出【例题1】代码

#include<bits/stdc++.h>
#define int long long   
#define lowbit(i) i&-i
using namespace std;

const int N=1e5+5;

inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9')
	    f=(ch!='-'),ch=getchar();
	while(ch<='9'&&ch>='0')
	    x=(x*10)+(ch^48),ch=getchar();
	return f?x:-x;    
}

int t1[N],t2[N];
int n,m,op,l,r,k,a[N];

void add(int p,int v)
{
	for(int i=p;i<=n;i+=lowbit(i))
	    t1[i]+=v,t2[i]+=v*p; 
}
int ask(int p)
{
	int ans=0;
	for(int i=p;i;i-=lowbit(i))
	    ans+=t1[i]*(p+1)-t2[i];
	return ans;    
}

signed main()
{
	n=read(),m=read();
	for(int i=1;i<=n;++i) 
		a[i]=read(),add(i,a[i]-a[i-1]);
	while(m--)
	{
		op=read(),l=read(),r=read();
		if(op==1)
		{
		    k=read();
		    add(l,k),add(r+1,-k);
		}    
	    if(op==2)
	        printf("%lld\n",ask(r)-ask(l-1));
	}
	return 0;
}

1.3 二维树状数组

标签:ch,limits,树状,int,sum,笔记,times,数组
From: https://www.cnblogs.com/fzefze/p/17615051.html

相关文章

  • C语言学习笔记(八)指针详解
    指针详解arr[i]=*(arr+i)=*(p+i)=p[i]字符指针charp*intmain(){ charch='w'; char*pc=&ch; return0;}intmain(){ chararr[]="abcdefg"; char*pc=arr; printf("%s\n",arr); printf("%s\n",pc); ......
  • C++STL 学习笔记
    C++STL学习笔记STL补充List链表list<int>mylist={}链表定义和初始化voidpush_front(constT& val)将val插入链表最前面voidpop_front()删除链表最前面的元素list.push_back() 增加一个新的元素在list的尾端list.pop_back() 删除list的......
  • 【学习笔记】【数学】计算几何基础
    点击查看目录目录前置知识:叉积与跨立实验前置知识:建议虽然是简单的前置知识,还是打开略过一遍。浮点数与误差分析(少用除法)向量相关向量向量,就是带有方向和大小两个属性的边,通常形式为\(\overrightarrow{AB}=(a_1,a_2)=A\)。运算与性质:判等:两点坐标重合。ilint......
  • C语言听课笔记
    %1f——double;%c——char;%p——&a;%s——char[]求两个数的较大值#include<stdio.h>int main(){ int num1=10; int num2=20; if (num1>num2)    printf("较大值是:%d\n",num1); else    printf("较大值是:%d\n",num2); return 0;}#include<stdio.h&......
  • PyTorch基础知识-新手笔记
    使用NumPy实现机器学习任务使用最原始的的NumPy实现一个有关回归的机器学习任务,不使用PyTorch中的包或类。代码可能会多一点,但每一步都是透明的,有利于理解每一步的工作原理。主要步骤如下:1)首先,给出一个数组x,然后基于表达式y=3x^2+2,加上一些噪声数据到达另一组数据。2)然后,构建......
  • 前端基础-数组方法
    数组方法备忘单:添加/删除元素:push(...items) ——向尾端添加元素,pop() ——从尾端提取一个元素,shift() ——从首端提取一个元素,unshift(...items) ——向首端添加元素,splice(pos,deleteCount,...items) ——从 pos 开始删除 deleteCount 个元素,并插入 i......
  • 线段树合并学习笔记
    基本思路线段树合并其实就是简单的暴力合并就可以了。一般是运用于权值线段树。通常是在每个节点都需要要一颗线段树才能维护答案,且有多个节点时,会使用线段树合并。但每个节点所有的权值不能太多,如果都是比较满的二叉树的话,时间复杂度就会很高。通常,加入值的数量跟节点数量在同......
  • STC15 外部中断编程笔记
    以STC15W4K58S4为例,可以将片上的外部中断资源分为“高级”和“低级”两类,EXINT0和EXINT1属于高级的,EXINT2~EXINT4属于低级的。“高级”的外部中断可以配置中断优先级,选择中断源;低级的则不行。EXINT0和EXINT1的配置这两个外部中断的配置寄存器都可位寻址,因此可以直......
  • 复习笔记|《计算机组成原理》
    参考教材:《计算机组成原理》蒋本珊➢前2类题看书中和课件中的有关概念。➢第3、4、5类题请注意平时的作业。如:❑扩展操作码设计❑有效地址的计算❑定点数乘、除运算❑存储器设计❑Cache计算❑微指令操作控制字段的设计第一章➢存储程序概念计算机硬件的组成,存储器控......
  • [学习笔记] Switch语句使用“===”进行比较
    JS中,switch语句会使用恒等计算符(===)进行比较。如上所述,下列代码中因为x定义为字符串10,而case为数字10,因此将不会弹出“HelloWorld”:var x="10";switch(x){    case 10:alert("Hello");}实际应用时应注意这点。......