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)的信息的统计