【模板】树状数组 2
题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数数加上x
2.求出某一个数的值
输入输出格式
输入格式:
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含2或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x 含义:输出第x个数的值
输出格式:
输出包含若干行整数,即为所有操作2的结果。
输入输出样例
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
样例说明:
故输出结果为6、10
分析:
又是一道模板题em。。。。不解释了。。。上代码。。。
CODE:
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 int n,m; 8 long long sum[555555]; 9 void add(int x,long long y){ 10 while (x<=n){ 11 sum[x]+=y; 12 x+=x&-x; 13 } 14 return; 15 } 16 long long ask(int x){ 17 long long ans=0; 18 while (x>=1){ 19 ans+=sum[x]; 20 x-=x&-x; 21 } 22 return ans; 23 } 24 long long fr(){ 25 char c=getchar();long long ans=0;bool flag=1; 26 while (c<'0'||c>'9'){if (c=='-') flag=0;c=getchar();} 27 while (c>='0'&&c<='9'){ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();} 28 if (flag) return ans;return -ans; 29 } 30 int main(){ 31 long long A,B,C,D; 32 scanf("%d%d",&n,&m); 33 for (int i=1;i<=n;i++){ 34 A=fr(); 35 add(i,A);add(i+1,-A); 36 } 37 while (m--){ 38 A=fr(); 39 if (A==1){ 40 B=fr(),C=fr(),D=fr(); 41 add(B,D);add(C+1,-D); 42 } 43 if (A==2){ 44 B=fr(); 45 printf("%lld\n",ask(B)); 46 } 47 } 48 return 0; 49 }