树状数组的基础
树状数组1
树状数组可以解决什么问题呢?
可以解决大部分区间上面的修改以及查询的问题,例如1.单点修改,单点查询,2.区间修改,单点查询,3.区间查询,区间修改,换言之,线段树能解决的问题,树状数组大部分也可以,但是并不一定都能解决,因为线段树的扩展性比树状数组要强.
为了更好的理解,下面咱们来看一道模板题点击跳转
显然,我们一开始会想到暴力的朴素做法,单点修改操作时间复杂度O(1),区间求和,暴力遍历区间每一个数再相加时间复杂度O(n),如果区间求和查询的次数为n次,那么中的时间复杂度为 O ( n 2 ) O(n^2) O(n2),对于大数据的题来说肯定会TLE,此时如果用树状数组的话复杂度可以讲到 O ( n l o g n ) . O(nlogn). O(nlogn).这时就要用到树状数组的奇妙了。
讲一些序列构建成树的形状,便于求和,便于增删,便于查找。
需要用到构建树状和查找结果两个函数,分别是
//构建函数
void add (int x,int y)
{while (x<=n){a[x]+=y;x+=lowbit(x);}
}
//查找函数
int search (int x)
{int ans=0;while (x){ans+=a[x];x-=lowbit(x);}return ans;
}
有了这两个函数,就易如反掌了写这个题。
这里说一下lowbit
lowbit() 函数用来 取一个二进制最低位的一与后边的0组成的数。可以用来判断一个数是不是2的幂次方,我们可以直接在头文件直接定义它。
接下来直接附上我的代码
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
#define fi first
#define se second
#define PII pair<int,int>
#define lowbit(x) (x&(-x))
using namespace std;
const int N=2e6+5;
int a[N];
int n,m;
void add (int x,int y)
{while (x<=n){a[x]+=y;x+=lowbit(x);}
}
int search (int x)
{int ans=0;while (x){ans+=a[x];x-=lowbit(x);}return ans;
}void solve()
{cin>>n>>m;for (int i=1;i<=n;i++){int x;cin>>x;add(i,x);}for (int i=1;i<=m;i++){int x,y,z;cin>>x>>y>>z;if (x==1) add(y,z);else {cout<<search(z)-search(y-1)<<'\n';}}return ;
}
signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int T=1;//cin >> T;while(T--) solve();return 0;
}
是一个树状数组的板子题,记住就可以了。
树状数组2
接下来是另一种树状数组的例题,基本思路和树状数组1大差不差,其中有些思路不一样,主要还是用到了上面所写的两个函数
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
#define fi first
#define se second
#define PII pair<int,int>
#define lowbit(x) (x&(-x))
using namespace std;
const int N=1e6+5;
int a[N],c[N];
int n,m;
void add (int x,int y)
{while (x<=n){c[x]+=y;x+=lowbit(x);}
}
int search (int x)
{int res=0;while (x){res+=c[x];x-=lowbit(x);}return res;
}
void solve()
{cin>>n>>m;for (int i=1;i<=n;i++){cin>>a[i];int x=a[i]-a[i-1];add(i,x);}for (int i=1;i<=m;i++){int x;cin>>x;if (x==1){int q,w,e;cin>>q>>w>>e;add(q,e);add(w+1,-e);}else if (x==2){int cnt;cin>>cnt;cout<<search(cnt)<<'\n';}}return ;
}
signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int T=1;//cin >> T;while(T--) solve();return 0;
}