• 数据结构-树状数组


    📑前言

    本文主要是【树状数组】——树状数组简单使用的文章,如果有什么需要改进的地方还请大佬指出⛺️

    🎬作者简介:大家好,我是听风与他🥇
    ☁️博客首页:CSDN主页听风与他
    🌄每日一句:狠狠沉淀,顶峰相见

    树状数组模板示例

    • 以1–8为例,构建树状数组
      在这里插入图片描述
    我们知道lowbit的性质是,奇数等于12的次方等于本身,偶数为第一次出现的0,如4100lowbit(4)=4
    A数组和C数组之间的关系为
    C1=A1
    C2=A1+A2
    C3=A3
    C4=A1+A2+A3+A4
    C5=A5
    C6=A5+A6
    C7=A7
    C8=A1+A2+A3+A4+A5+A6+A7+A8
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    模板代码:

    package 难点攻克;
    
    import java.util.Arrays;
    
    public class TreeArray {
    
    	static int[] A;//原始的数据
    	static int[] C;//树状数组
    	static int n;//数组的元素个数
    	public TreeArray(int[] A) {
    		this.A=new int[A.length];
    		n = A.length;
    		C = new int[n+1];//c[0]不用
    		for(int i=1;i<=A.length;i++) {
    			update(i, A[i-1]);
    		}
    	}
    	public static int lowbit(int x) {
    		return x&(-x);
    	}
    	
    	public static void update(int i,int val) {  
    		//原来的值A[i-1],现在的值是val
    		System.out.println("val:"+val+" i:"+A[i-1]);
    		int data = val-A[i-1];//新旧值之间的差距
    //		System.out.println("data:"+data);
    		A[i-1]=val;//将A的第i个元素(生活中,计算机里面i-1)修改新的值val
    		for(int pos=i;pos<=n;pos=pos+lowbit(pos)) {
    			C[pos] += data;
    		}
    	}
    	
    	public static int sumRange(int start,int end) {
    		if(start<1 || start>n || end<1 ||end>n) {
    			return -1;
    		}else {
    			return sum02k(end)-sum02k(start-1);
    		}
    		//sum02k(end)=A1+A2+...+Astart-1 + Astart +...+Aend
    		//sum02k(end)=A1+A2+...+Astart-1
    	}
    	
    	public static int sum02k(int pos) {//c[pos]+c[pos-lowbit[pos]]+...
    		int sum = 0;
    		for(int i=pos;i>=1;i=i-lowbit(i)) {
    			sum=sum+C[i];
    		}//sum(A(1)->A(7)) =>c[7]+C[7-lowbit[7])+c[6-lowbit(6))=c7+c6+c4
    		return sum;
    	}
    	
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    	int[] a = {1,2,3,4,5,6,7,8};
    	TreeArray t = new TreeArray(a);
    	System.out.println(Arrays.toString(t.C));
    	t.update(3, 99);
    	System.out.println(Arrays.toString(t.A));
    	System.out.println(Arrays.toString(t.C));
    	System.out.println("前2个的和:"+t.sum02k(2));
    	System.out.println("前6个的和:"+t.sum02k(6));
    	System.out.println("2-6个的和:"+t.sumRange(2, 6));
    	}
    
    }
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    1208.小球与盒子

    package 难点攻克;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.StreamTokenizer;
    import java.util.Arrays;
    
    public class Main {
    
    	static long[] A;
    	static long[] C;
    	static int n;
    	public Main(long[] A) {
    		this.A = new long[A.length];
    		n = A.length;
    		C = new long[n+1];
    		for(int i=1;i<=n;i++) {
    			update(i, A[i-1]);
    		}
    	}
    	public static int lowbit(int x) {
    		return x&(-x);
    	}
    	public static void update(int i,long val) {
    		long data = val;
    		A[i-1]=val;
    		for(int pos=i;pos<=n;pos=pos+lowbit(pos)) {
    			C[pos]+=data;
    		}
    	}
    	public static long sum02k(int i) {
    		long ans = 0;
    		for(int pos=i;pos>=1;pos=pos-lowbit(pos)) {
    			ans+=C[pos];
    		}
    		return ans;
    	}
    	
    	public static long Sum(int start,int end) {
    		return sum02k(end)-sum02k(start-1);
    	}
    	public static void main(String[] args) throws IOException {
    		// TODO Auto-generated method stub
    		StreamTokenizer sc = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    		sc.nextToken();
    		int n = (int)sc.nval;
    		long nums[] = new long[n];
    		Main t = new Main(nums);
    		sc.nextToken();
    		int m =(int)sc.nval;
    		while(m-->0) {
    			sc.nextToken();
    			int op=(int)sc.nval;
    			sc.nextToken();
    			int x=(int)sc.nval;
    			sc.nextToken();
    			int y=(int)sc.nval;
    			if(op==1) {
    				update(x, y);
    			}else {
    				System.out.println(Sum(x, y));
    			}
    		}
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    📑文章末尾

    在这里插入图片描述

  • 相关阅读:
    2023年05月 C/C++(八级)真题解析#中国电子学会#全国青少年软件编程等级考试
    <能力清单>笔记与思考
    linux驱动程序40:页内存分配
    常见面试题-TCP三次握手四次挥手
    web网页设计期末课程大作业——汉中印象旅游景点介绍网页设计与实现19页面HTML+CSS+JavaScript
    VSCode自定义代码块详解
    ASW3410数据手册|ASW3410设计参数|USB3.0高速数据开关切换IC说明书
    中国多元醇行业发展态势良好 重点关注海外市场
    JavaScript快速入门
    工作以来一直在CRUD,Spring源码该怎么阅读?这份价值百万的源码解析让你如有神助!
  • 原文地址:https://blog.csdn.net/weixin_61494821/article/details/136528964