树状数组求区间和例题练习(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 ;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nuist__NJUPT

给个鼓励吧,谢谢你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值