树状数组求区间和例题练习(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单点修改区间查询