首页 > 其他分享 >树状数组的思想复习

树状数组的思想复习

时间:2023-06-04 16:47:02浏览次数:63  
标签:单点 复习 树状 int lowbit 查询 数组

树状数组的复习

前言:

学树状数组的时候第一没理解透彻,第二还没写博客用于复习,所以这里写一下用于复习

树状数组:

作用:logn

logn时间实现单点修改区间查询;区间修改单点查询;区间修改区间查询。

但是区间修改区间查询还是线段树好,因为扩展性很强

特点:父子节点关系

例如当前节点为x,那么fa[x]=x+lowbit(x);

做题方法

1.单点修改区间查询

a[i]表示原数组,t[i]表示前缀数组,然后在x<=n的范围内不断地+lowbit(x)更新父亲的t数组即可

那怎么查询呢,

先来个特殊的,1-x的查询,例如x=7时,sum[7]=t[7]+t[6]+t[4] ,我们进一步发现,6=7-lowbit(7),4=6-lowbit(6),所以我们可以通过不断的-lowbit操作来实现求和

那么一段区间的就求差就行了

2.区间修改单点查询

原数组a[i],a[i]差分数组b[i],用上面的方法维护两次单点修改的b数组即可

模板:P3374 【模板】树状数组 1 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
int a[500005];
int t[500005];
int lowbit(int x){
	return x&(-x);
}
void add(int x,int val){
	for(int i=x;i<=n;i+=lowbit(i)){
		t[i]+=val;
	}
}
int ask(int x){
	int ret=0;
	for(int i=x;i>=1;i-=lowbit(i)){
		ret+=t[i];
	}
	return ret;
}
signed main(){
	ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i=1;i<=n;i++){
		cin >> a[i];
		add(i,a[i]);
	}
	while(m--){
		int a,b,c;
		cin >> a >> b >> c;
		if(a==1){
			add(b,c);
		}
		else{
			cout<<ask(c)-ask(b-1)<<endl;
		}
	}
}
	

区间修改单点查询不也EZ?https://www.luogu.com.cn/record/112034120

练习题详见铃狐sama的竞赛复习计划 - 铃狐sama - 博客园 (cnblogs.com)

标签:单点,复习,树状,int,lowbit,查询,数组
From: https://www.cnblogs.com/linghusama/p/17455866.html

相关文章

  • 云计算期末复习
    云计算期末复习目录云计算期末复习一、云计算简介云计算主要服务模式云计算主要部署模式二、云计算技术什么是云计算与边缘计算云计算的特点虚拟化技术的概念虚拟化技术的特点虚拟化技术的优势什么是容器技术什么是DockerDocker概述\三大核心概念三、云原生云原生的概念常考命令......
  • [USACO07JAN] Balanced Lineup G(树状数组)
    题目大意:给出长度为n的数组和q个询问,每次问(x,y)区间内最大值和最小值的差是多少思路:1.适合用树状数组做此区间求值,首先要明白普通的树状数组的tree[x]表示区间(x-(x&-x),x]的区间和,现在改为求最值,则tree[x]表示为区间(x-(x&-x),x]的最值,建树部分稍作改变即可,询问部分......
  • 交换数组
    #include<iostream>#include<iomanip>usingnamespacestd;intmain(intargc,char**argv){ inta[10][10],c,d; for(inti=1;i<=5;i++){ for(intj=0;j<5;j++){ cin>>a[i][j]; } } cin>>c>>d; for(inti=0;i<=5;......
  • 二维数组
    //两个矩阵的乘积之和#include<iostream>usingnamespacestd;intmain(){inta[5][5],b[5][5],sum=0;for(inti=0;i<5;i++){for(intj=0;j<5;j++){cin>>a[i][j];}}for(inti=0;i<5;i++){......
  • 6.6 数组排序案例分析
    冒泡排序classArrayUtil{publicstaticvoidsort(intdata[]){for(intx=0;x<data.length;x++){for(inty=0;y<data.length-x-1;y++){//注意这里的-x-1含义;if(data[y]<data[y+1]){......
  • 数组去重
    数组去重是前端开发中比较常见的问题,有多种方法可以实现:使用Set去重(ES6)constarr=[1,1,2,3,4,4,5];constuniqueArr=[...newSet(arr)];console.log(uniqueArr);//[1,2,3,4,5]使用filter去重constarr=[1,1,2,3,4,4,5];constuniqueArr=......
  • 一维数组名的sizeof计算大小
    intmain(){ //数组名是首元素地址 //1,sizeof(数组名)——数组名表示整个数组 //2,&数组名——表示整个数组 //除这两种情况外,都是首元素地址 // inta[]={1,2,3,4}; printf("%d\n",sizeof(a));//szieof(数组名),计算的是数组的总大小—单位字节—16 printf("%d\n",sizeof(a......
  • 6.4 二维数组
    定义一个静态的二维数组,并用2种循环语句给输出publicclassHelloWorld{publicstaticvoidmain(String[]args){intdata[][]=newint[][]{{1,2,3,4,5},{4,5,6},{7,8,9,10}};for(intx=0;x<data.length;x++)......
  • 6.5 数组与方法
    demo1publicclassHelloWorld{publicstaticvoidmain(String[]args){//对于引用数据类型而言,主要的特点是可以与方法进行引用传递//而数组本身也是引用数据类型//demo:实现一个数组的引用传递intdata[]=newint[]{1,2......
  • 6.2 数组引用传递分析
    数组是引用传递publicclassHelloWorld{publicstaticvoidmain(String[]args){//数组是引用数据类型;就一定会发生引用传递;intdata[]=newint[]{10,20,30};inttemp[]=data;temp[0]=99;//data[0]会跟着改变;......