学习笔记:树状数组
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
相关文章推荐
- OleView.exe:查看机器上的COM 组件。
- 找东西
- PSR 规范 (精简版)
- 【spring】BeanFactoryPostProcessor简介
- 为什么不能往Android的Application对象里存储数据
- Ffmpeg视音频编解码零基础学习
- hibernate 4.x org.hibernate.LazyInitializationException异常解决
- Android 动画
- JAVA反射系列之Field,java.lang.reflect.Field使用获取方法。
- mongodb入门学习小记
- Unity3D shader描边效果源码
- CSS Overflow属性详解
- 二叉树二叉链表存储结构《头文件:#include "BiTreeHead.h"》
- 证件识别接口PHP调用示例
- JavaScript 字符串方法大全
- Oracle中*和其他字段组合查询的说明
- 实习杂记(28):SurfaceView+ListView+MediaPlayer滑动时候灰色覆盖等问题
- java反射詳解
- sort排序注意事项
- iOS js调用oc方法