数组数组用于维护区间信息,简洁的几行的代码可以单点操作/区间查询,或者区间操作与单点查询。
虽然功能小于线段树,但是在相同功能的实现上,两者复杂度差不多。线段树
我们先介绍第一个功能
先看一下树状数组的图
我们观察出他的几个性质:
我们如何求最低位1呢?
假如我们对x+k,那么他的祖先们都需要,去祖先的更新方法就是+lowbit
void add(int x,int k)
{for (int i=x; i<=n; i+=i&-i)t[i]+=k;
}
那么我们从t[x]一直减最低位1,累加到t[0]即可
ll ask(int x)
{ll ans=0;for (int i=x; i; i-=i&-i)ans+=t[i];return ans;
}
#include
using namespace std;
#define ll long long
const int N = 5e5 + 10;
int a[N],t[N];
int n;
void add(int x,int k)
{for (int i=x; i<=n; i+=i&-i)t[i]+=k;
}ll ask(int x)
{ll ans=0;for (int i=x; i; i-=i&-i)ans+=t[i];return ans;
}int main()
{int m,p,x,y;cin>>n>>m;for (int i=1; i<=n; ++i)cin>>a[i],add(i,a[i]);while (m--){cin>>p>>x>>y;if (p==1){add(x,y);}else if (p==2){cout<
代码没什么区别
int b[N];
int n;
void add(int x,int k)
{for (int i=x; i<=n; i+=i&-i)b[i]+=k;
}
ll ask(int x)
{ll ans=0;for (int i=x; i; i-=i&-i)ans+=b[i];return ans;
}
#include
using namespace std;
#define ll long long
const int N = 5e5 + 10;int b[N];
int n;
void add(int x,int k)
{for (int i=x; i<=n; i+=i&-i)b[i]+=k;
}
ll ask(int x)
{ll ans=0;for (int i=x; i; i-=i&-i)ans+=b[i];return ans;
}int main()
{int m,p,x,y,k;cin>>n>>m;for (int i=1; i<=n; ++i)cin>>x,add(i,x),add(i+1,-x);while (m--){cin>>p;if (p==1){cin>>x>>y>>k;add(x,k),add(y+1,-k);}else if (p==2){cin>>x;cout<