您的位置:首页 > 其它

学习笔记:树状数组

2016-07-06 16:07 281 查看

一、树状数组是干什么的?

平常我们会遇到一些对数组进行维护查询的操作,比较常见的如,修改某点的值、求某个区间的和,而这两种恰恰是树状数组的强项!当然,数据规模不大的时候, 对于修改某点的值是非常容易的,复杂度是O(1),但是对于求一个区间的和就要扫一遍了,复杂度是O(N),如果实时的对数组进行M次修改或求和,最坏的 情况下复杂度是O(M*N),当规模增大后这是划不来的!而树状数组干同样的事复杂度却是O(M*lgN),别小看这个lg,很大的数一lg就很小了,这 个学过数学的都知道吧,不需要我说了。申明一下,看下面的文章一定不要急,只需要看懂每一步最后自然就懂了。

二、树状数组怎么干的?

先看两幅图(网上找的,如果雷同,不要大惊小怪~),下面的说明都是基于这两幅图的,左边的叫A图吧,右边的叫B图:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstdlib>
#include<iomanip>
#include<cassert>
#include<climits>
#define maxn 100001
#define F(i,j,k) for(int i=j;i<=k;i++)
#define M(a,b) memset(a,b,sizeof(a))
#define FF(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x7fffffff
#define maxm 21
//#define LOCAL
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m;
int a[maxn],c[maxn];
int last[maxn];
inline int lowbit(int x)
{
return x&-x;
}
inline void add(int k,int num)
{//建树&增加常数
last[k]+=num;
while(k<=n)
{
c[k]+=num;
k+=lowbit(k);
}
//    F(i,1,n)cout<<c[i]<<" ";cout<<endl;
return;
}
inline void add_interval(int l,int r,int k)
{//区间增减【慢】(nlogn)
F(i,l,k){
last[i]+=k;
}
F(i,l,r){
add(i,k);
}
//    F(i,1,n)cout<<c[i]<<" ";cout<<endl;
return;
}
inline void change(int x,int y)
{//单点修改
int aa,bb;
aa=last[x];//cout<<aa<<endl;
y=y-aa;//cout<<y<<endl;
add(x,y);//cout<<y<<endl;
//    F(i,1,n)cout<<c[i]<<" ";cout<<endl;
return;
}
inline int query_pro(int k)
{//求前缀和
int sum=0;
while(k)
{
sum+=c[k];
k-=lowbit(k);
}
return sum;
}
inline int query_single(int k)
{//单点查询
int sum=0;
sum=query_pro(k)-query_pro(k-1);
return sum;
}
inline int query_sum(int l,int r)
{//区间求和
int sum=0;
sum=query_pro(r)-query_pro(l-1);
return sum;
}
int main()
{
std::ios::sync_with_stdio(false);//cout<<setiosflags(ios::fixed)<<setprecision(1)<<y;
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif
cin>>n;
F(i,1,n){
cin>>a[i];
add(i,a[i]);
}
/*
int opt,x,y,z;
while(1)
{
cin>>opt;
switch(opt)
{
case 1:cin>>x>>y;add(x,y);break;
case 2:cin>>x>>y>>z;add_interval(x,y,z);break;
case 3:cin>>x>>y;change(x,y);break;
case 4:cin>>x;cout<<query_single(x)<<endl;break;
case 5:cin>>x;cout<<query_pro(x)<<endl;break;
case 6:cin>>x>>y;cout<<query_sum(x,y)<<endl;break;
}
} */
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: