【模板】树状数组1

tech2024-04-10  7

前往:我自己搭建的博客

题目

洛谷P3374树状数组 1

题解

能够用树状数组维护的值必须满足区间加(将两个区间合并)和区间减(将一个区间拆开)(例:区间和可以加减,但区间最值只能加不能减)。树状数组的作用是动态维护区间数据和动态查询,基本用途是维护区间和(以下讲解都以区间和为例)。

lowbit运算:lowbit(n)定义为非负整数n在二进制表示下“最低位的1和其后面所有的0”构成的数值。(例子:n=10=(1010),lowbit(n)=2=(10) )

C++中,在补码表示下,~n=-1-n, lowbit(n)=n&(~n+1)=n&(-n)。

另c[x]表示序列的区间[x-lowbit(x)+1,x]中的所有数的和,于是区间[1,x]就可以分为(log x)段,相当于二进制分解的过程。(例:x=7=(111),[1,7]分成[1,4],[5,6],[7,7],区间长度分别为4,2,1)

代码

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=5e5+5; int n,m; int sum[maxn]; inline int lowbit(int x) {return x&(-x);} inline void add(int x,int y) //给第x个位置加y { for( ;x<=n;x+=lowbit(x)) sum[x]+=y; } inline int ask(int x) //查询区间[1,x]的和 { int ans=0; for( ;x;x-=lowbit(x)) ans+=sum[x]; return ans; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); add(i,x); } for(int i=1;i<=m;i++) { int t,x,y; scanf("%d%d%d",&t,&x,&y); if(t==1) add(x,y); else {int ans=ask(y)-ask(x-1); printf("%d\n",ans);} } return 0; }
最新回复(0)