树状数组求区间和例题练习(Java实现)

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组求区间和例题练习(Java实现)相关的知识,希望对你有一定的参考价值。

树状数组求区间和例题练习(Java实现)

题目链接地址戳这里!


/**
 * 树状数组1:
 * 单点更新,单点查询
 * 题目链接:https://www.luogu.com.cn/problem/P3374
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main 
    static int n, m ;
    static int x, y, z ;
    static int [] c = new int [5000000] ;
    static List<Integer> list = new ArrayList<>() ;
    public static void main(String[] args) 
        Scanner input = new Scanner(System.in) ;
        n = input.nextInt() ;
        m = input.nextInt() ;
        for(int i=1; i<=n; i++)
            int a = input.nextInt() ;
            update(a, i) ;
        
        for(int i=1; i<=m; i++)
            x = input.nextInt() ;
            y = input.nextInt() ;
            z = input.nextInt() ;
            if(x == 1)
                update(z, y);
            
            if(x == 2)
                list.add(query1(z) - query1(y-1)) ;
            
        
        for(int i=0; i<list.size(); i++)
            System.out.println(list.get(i));
        
    

    private static int query1(int i) 
        int ans = 0 ;
        while(i>0)
            ans += c[i] ;
            i -= lowbit(i) ;
        
        return ans ;
    

    private static void update(int a, int i) 
        while(i<=n) 
            c[i] += a;
            i += lowbit(i);
        
    

    private static long lowbit(int i)
        return i & (-i) ;
    

题目链接戳这里!!!

/**
 * 树状数组2
 * 区间更新,单点查询
 * 题目链接:https://www.luogu.com.cn/problem/P3368
 */

import java.util.Scanner;

public class Main 
    static int N, M ;

    static int [] c = new int [5000000] ;
    public static void main(String[] args) 
        Scanner input = new Scanner(System.in) ;
        N = input.nextInt() ;
        M = input.nextInt() ;
        int now , last = 0 ;
        for(int i=1; i<=N; i++)
            now = input.nextInt() ;
            updates(i, now-last) ; //构造差分树状数组
            last = now ;
        
        for(int i=0; i<M; i++)
            int a = input.nextInt() ;
            if(a == 1)
                int x = input.nextInt() ;
                int y = input.nextInt() ;
                int k = input.nextInt() ;
                updates(x, k);
                updates(y+1, -k);
            
            if(a == 2)
                int x = input.nextInt() ;
                System.out.println(query(x)) ;
            
        
    

    private static long query(int x) 
       long ans = 0 ;
        while(x>0)
            ans += c[x] ;
            x -= lowbits(x) ;
        
        return ans ;
    

    private static void updates(int i, int a) 
        while(i<=N)
            c[i] += a ;
            i += lowbits(i) ;
        
    

    private static long lowbits(int i) 
        return (-i) & i ;
    


题目链接戳这里!!!


import java.util.Arrays;
import java.util.Scanner;

/**
 * 楼兰图腾
 * 题目链接:https://www.acwing.com/problem/content/243/
 */
public class Main 
    static int N = 2000000 ;
    static int n ;
    static int [] a ;
    static long [] c = new long [N] ;
    static long [] left1 = new long [N] ;
    static long [] left2 = new long [N] ;
    static long [] right1 = new long [N] ;
    static long [] right2 = new long [N] ;
    public static void main(String[] args) 
        Scanner input = new Scanner(System.in) ;
        n = input.nextInt() ;
        a = new int[n+1] ;
        for(int i=1; i<=n; i++)
            a[i] = input.nextInt() ;
        
        for(int i=1; i<=n; i++)
            left1[i] = query(a[i]-1) ; //左侧小于它的个数
            left2[i] = query(n) - query(a[i]) ; //左侧大于它的个数
            update(a[i],1); //更新树状数组
        
        Arrays.fill(c, 0);
        long res1 = 0, res2 = 0 ;
        for(int i=n; i>0; i--)
            right1[i] = query(a[i]-1) ; //右侧小于它个数
            right2[i] = query(n) - query(a[i]) ;//右侧大于它的个数
            update(a[i], 1);
            res1 += left2[i] * right2[i] ;
            res2 += left1[i] * right1[i] ;
        
        System.out.println(res1 + " " + res2) ;


    
    private static long lowbit(long i)
        return (-i) & i ;
    
    private static void update(int i, long x)
        while(i <= n)
            c[i] += x ;
            i += lowbit(i) ;
        
    
    private static long query(int i)
        int ans = 0 ;
        while(i>0)
            ans += c[i] ;
            i -= lowbit(i) ;
        
        return ans ;
    


题目链接戳这里!!!

import java.util.Scanner;

/**
 * 校门外的树
 * 题目链接:https://loj.ac/p/10115
 *
 */
public class Main
    static int n, m ;
    static int [] c1 = new int [50010] ;
    static int [] c2 = new int [50010] ;
    public static void main(String[] args) 
        Scanner input = new Scanner(System.in) ;
        n = input.nextInt() ;
        m = input.nextInt() ;
        for(int i=1; i<=m; i++)
            int k = input.nextInt() ;
            int x = input.nextInt() ;
            int y = input.nextInt() ;
            if(k==1)
                add(c1, x) ; //c1数组记录左括号的个数
                add(c2, y) ; //c2数组记录右括号的个数
            
            if(k==2)
                System.out.println(query(c1, y) - query(c2, x-1));
            
        
    

    private static long query(int[] c, int i) 
        long ans = 0 ;
        while(i>0)
            ans += c[i] ;
            i -= lowbit(i) ;
        
        return ans ;
    

    private static void add(int[] c, int i) 
        while(i<=n)
            c[i] ++ ;
            i += lowbit(i) ;
        
    

    private static long lowbit(int i) 
        return (-i) & i ;
    


以上是关于树状数组求区间和例题练习(Java实现)的主要内容,如果未能解决你的问题,请参考以下文章

luoguP3374ybtoj树状数组例题1单点修改区间查询

ybtoj树状数组差分例题4区间修改区间查询

luogu P4514ybtoj树状数组课堂过关差分 例题6区间修改区间查询 & 上帝造题的七分钟

树状数组的操作

浅析树状数组

树状数组求区间和 和 单点更新