洛谷 P3368 【模板】树状数组 2(区间加,单点查询)

题目链接

https://www.luogu.org/problemnew/show/P3368

树状数组

最基础的用法:https://www.cnblogs.com/yinyuqin/p/10961243.html

在这里实现的是区间加,单点查询。


一说到区间加,我们就会想到差分序列,关于差分序列的用法:https://www.cnblogs.com/yinyuqin/p/10961325.html

所以我们在树状数组中维护的不是单点了,而是差分序列。

为什么要用树状数组呢?

因为归根结底,树状数组还是能用O(1)的时间复杂度求出1...n的区间和,因为要求差分序列的前缀和,所以用树状数组来维护。

与最基础的用法唯一的不同之处就是在区间加的时候update两次,修改两个点,和差分序列用法相同。

其他的无异。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int n,m,a[500005],d[500005],c[500005]; 
 5 int lowbit(int x){
 6     return x&(-x);
 7 }
 8 void update(int x,int v){
 9     for(int i=x;i<=n;i+=lowbit(i)){
10         c[i]+=v;
11     }
12 }
13 int query(int x){
14     int res=0;
15     for(int i=x;i>0;i-=lowbit(i)){
16         res+=c[i];
17     }
18     return res;
19 }
20 int main()
21 {
22     cin>>n>>m;
23     for(int i=1;i<=n;i++){
24         scanf("%d",&a[i]);
25         d[i]=a[i]-a[i-1];//差分序列 
26         update(i,d[i]);
27     }
28     for(int i=1;i<=m;i++){
29         int k;
30         cin>>k;
31         if(k==1){
32             int x,y,v;
33             scanf("%d%d%d",&x,&y,&v);
34             update(x,v);//注意要修改两个点 
35             update(y+1,-v);
36         }
37         else{
38             int x;
39             scanf("%d",&x);
40             cout<<query(x)<<endl;
41         }
42     }
43     return 0;
44 }

 

posted @ 2019-06-01 23:12  尹昱钦  阅读(185)  评论(2编辑  收藏  举报