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)的信息的统计
![](https://i-blog.csdnimg.cn/blog_migrate/e608273e983ed61f9a82d7984b23ec28.png)