洛谷3368 - 树状数组 区间更新 单点查询

import java.io.BufferedInputStream;
import java.util.Scanner;

public class Main{
	final static int maxn = 500100;
	static long[] tre = new long[maxn+5];
	static long[] a = new long[maxn+5];
	static int n,m;
	static void update(int x,long add) {
		while(x<=n) {
			tre[x]+=add;
			x+=x&(-x);
		}
		//将所有管辖的区间范围内全部加上add 
	}
	
	static long sum(int x) {
		long s = a[x];
		while(x>0) {
			s+=tre[x];
			x-=x&(-x);
		}//将所有管到x下标处的区间所有的加和信息全部统计出来
		return s;
		//修改后的策略是当+add 的时候表示要 x~maxn + add 
	}
	
	public static void main(String[] args) {
		Scanner sc  = new Scanner(new BufferedInputStream(System.in));
		n = sc.nextInt();
		m = sc.nextInt();
		for(int i=1;i<=n;i++){
			a[i] = sc.nextLong();
		}
		
		while(m--!=0) {
			int f;
			f = sc.nextInt();
			if(f==1) {
				int s,e;
				long add;
				s = sc.nextInt();
				e = sc.nextInt();
				add = sc.nextLong();
				update(s,add);
				update(e+1,-add);
				//这里表示 s ~ e + add 就先
			}
			else {
				int x;
				x = sc.nextInt();
				System.out.println(sum(x));
			}
		}
	}
}

#include<cstdio>
#include<iostream>
using namespace std;
const int maxn = 500010;
int n,m,a[maxn],c[maxn];
void update(int x,int add){
	while(x<=n){
		c[x]+=add;
		x+=x&(-x);
	}
}
int sum(int x){
	int s = a[x];
	while(x>0){
		s+=c[x];
		x-=x&(-x);
	}
	return s;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	while(m--){
		int f;
		scanf("%d",&f);
		if(f==1){
			int s,e,add;
			scanf("%d%d%d",&s,&e,&add);
			update(s,add);
			update(e+1,-add);
		}
		else{
			int x;
			scanf("%d",&x);
			printf("%d\n",sum(x));
		}
	} 
	return 0;
 } 

题意就是对一个区间上的数据区间修改 单点查询

几乎同样的代码 c++的AC java的三个RE 太奇怪了
完全找不到RE的可能 
不可能除以零 
不可能出现越界 已经多开了不小的范围 也不会小于零

这道题完全不必用差分数组
只用一个原始数组和修改数组即可

其中update(x,add)表示在x~n区间都加上add 
区间修改就是再加上一个update(e,-add)即可

这样树状数组中统计的信息 就由基本的当前数的lowbit个数的信息 变成了现在的x~n的区间公共的修改信息

那么sum(x)的时候 为了单点求到正确的和 

我们需要统计所有小于x的点 的修改 信息 因为每一个小于x的点的修改信息 都是对x~n的修改
比如查询5 我们要通过-lowbit 把4的信息获取到 而4的信息 又是(1,2,3,4)的信息的统计



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
树状数组(Fenwick Tree)是一种用于高效处理区间修改和单点查询的数据结构。下面我将介绍如何使用树状数组实现区间修改和单点查询。 首先,我们需要定义树状数组的数据结构。树状数组由一个数组和一组操作组成,其中数组用于存储数据,操作用于更新查询数组中的值。 下面是一个示例的树状数组实现: ```python class FenwickTree: def __init__(self, n): self.size = n self.tree = [0] * (n + 1) def update(self, idx, delta): while idx <= self.size: self.tree[idx] += delta idx += idx & -idx def query(self, idx): res = 0 while idx > 0: res += self.tree[idx] idx -= idx & -idx return res def range_update(self, l, r, delta): self.update(l, delta) self.update(r + 1, -delta) def point_query(self, idx): return self.query(idx) ``` 在上面的代码中,我们定义了一个FenwickTree类,通过构造函数`__init__`来初始化树状数组,并使用`size`来表示数组的大小。`tree`数组用于存储数据。`update`方法用于更新指定位置的值,`query`方法用于查询指定位置之前的求和结果。`range_update`方法用于对指定区间进行修改,`point_query`方法用于查询单个位置的值。 下面是一个示例的使用场景: ```python # 示例使用 n = 10 tree = FenwickTree(n) # 区间修改 [2, 6] 的值加 3 tree.range_update(2, 6, 3) # 查询位置 5 的值 value = tree.point_query(5) print(value) ``` 在上面的示例中,我们创建了一个大小为10的树状数组,并对区间[2, 6]的值进行了修改,将其加3。然后,我们查询了位置5的值,结果为3。 希望以上内容能够帮助到你实现树状数组区间修改和单点查询。如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值