专栏文章
题解:P3368 【模板】树状数组 2
P3368题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipooi03
- 此快照首次捕获于
- 2025/12/03 15:26 3 个月前
- 此快照最后确认于
- 2025/12/03 15:26 3 个月前
题目大意
树状数组模板题,要求在 的数据下实现区间加和单点查询。
大体思路
树状数组教学
树状数组其实是一个相当优美的算法了,其中使用的 lowbit 十分精妙。
CPP//lowbit
int lowbit(int k){
return k&(-k);
}
lowbit 的含义是什么呢?为什么 lowbit 能够这么快速的实现此类问题呢,我们先来看一张图(from OI-Wiki)。
这里运用了负数的存储特性,负数是用补码存储的,例如当 为奇数时,最后一位是 取反加一并没有进位,所以 结果正好是 ,相同的我们可以推得,如果 为偶数,结果是 最大的 ,其中 为整数,有兴趣的小伙伴可以自己分类讨论推导一下,探讨偶数时可以分成 和 两种,然后就可以发现后者其实是用一个奇数左移 位来表示的(说多了)。
,发现 刚好是满足上图的,上图恰好满足 。
举个例子,,正好 就是存 ,,正好 就是存 ,, 就是存 。
也就是说,树状数组通过使用 lowbit 来存储一部分节点,能用很少的空间实现一部分线段树的功能,而且常数较小。
回到本题
本题中,由于一开始的数是固定的,所以我们只需要用树状数组来记录变更的值。
区间修改单点查询,我们使用差分数组思想。
- 区间加
我们要进行的区间加操作,需要从 扫到 ,对差分数组进行操作。
CPPvoid add(int x,int k){
while(x<=n){
t[x]+=k;
x+=lowbit(x);
}
}
毕竟是差分数组,所以我们在主函数内调用时需要这样。
CPPadd(x,z);
add(y+1,-z);
- 单点查询
我们要进行单点查操作,就需要从 扫到 ,每一个修改都要加起来,就是把差分前缀和起来。
CPPint sum(int x){
int ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
Code
CPP#include<bits/stdc++.h>
using namespace std;
int n,m;
int t[500005];int a[500005];
int lowbit(int k){
return k& -k;
}
void add(int x,int k){
while(x<=n){
t[x]+=k;
x+=lowbit(x);
}
}
int sum(int x){
int ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
int c;
cin>>c;
if(c==1){
int x,y,z;
cin>>x>>y>>z;
add(x,z);
add(y+1,-z);
}
else{
int x;
cin>>x;
int ans=sum(x)+a[x];
cout<<ans<<endl;
}
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...