树状数组基础及运用
来源:互联网 发布:第四届淘宝村高峰论坛 编辑:程序博客网 时间:2024/06/04 00:54
树
#include <cstdio> #include <cstring> #define maxn 50047 int c[maxn], a[maxn]; int n,t; int Lowbit(int x) // 2^k { return x&(-x); } void update(int i, int x)//i点增量为x { while(i <= n) { c[i] += x; i += Lowbit(i); } } int sum(int x)//区间求和 [1,x] { int sum=0; while(x>0) { sum+=c[x]; x-=Lowbit(x); } return sum; } int Getsum(int x1,int x2) //求任意区间和 { return sum(x2) - sum(x1-1); } int main() { int i , j; scanf("%d",&t); int count = 0; while(t--) { count++; memset(a,0,sizeof(a)); memset(c,0,sizeof(c)); scanf("%d",&n); for(i = 1; i <= n; i++) //i须从1开始 { scanf("%d",&a[i]); update(i,a[i]); //初始的人数 } printf("Case %d:\n",count); char oper[11]; while(scanf("%s",oper)==1) { if(strcmp(oper,"End")==0) break; scanf("%d%d",&i,&j); if(strcmp(oper,"Query")==0) { printf("%d\n",Getsum(i,j)); } if(strcmp(oper,"Add")==0) //表示第i个营地增加j个人 { a[i] += j; update(i,j); } if(strcmp(oper,"Sub")==0) //表示第i个营地减少j个人 { a[i] -= j; update(i,-j); } } } return 0; }
状数组的基础是一个被构造出来的式子:C[i]=A[i]+A[i-1]+....+A[i-2^k+1];k代表i的二进制的最后连续0的个数 比如 对于1000和101000,k=3。至于这个式子是怎么被构造出来的,k为什么要代表这个。因为二进制的思想。
根据这个图来看节点与其子树的关系
接下来则很容易发现 节点和子节点的是有关系的,这种关系就是 i=j+lowbit(j); lowbit是j的最低位1所代表的数字 比如对于 1000(8的二进制) 1000=100+lowbit(100)=110+lowbit(110)=111+lowbit(111);
这个关系是树状数组的核心,有了这个关系,我们可以把子区间的变化以log2n的次数传递上去
那我们也知道了 当我们要求 1-n的和时,我们同样把n表示为2进制,我们知道 C[i]=A[i]+A[i-1]+....+A[i-2^k+1]; 所以对于i 是不是我们只要把他所有的1都用上 就可以表示1-n的和?
举个例子 求1-11000 则 Sum(11000)=C[11000]+C[10000]; 因为 根据C[i]的构造方法 C[i]是从A[i]开始的2^k个元素的和,则C[11000]求了A[11000] A[10111] A[10110] A[10101] A[10100] A[10010] A[10001] 这2^k个数 然后接着C[10000]求出了剩下 10000个元素的和 到了这我们就大概了解了树状数组的发明者的天才的构造是从何而来的了 普通的求1-n的和储存的数据太多,而这位天才则想,我们能不能根据二进制的思想来储存这些值呢?任何一个数,都可以由若干个二进制数相加而成,如果我们在求Sum(n)之前就知道了 n对应的二进制数从最低位开始,每个1所代表的数字的前2^i个数的和,我们不就能在时间复杂度log2(n)内求出所有的值 比如 101110 我们如果知道 101110->101101 101100->101001 101000->100001 100000->1各自的和,就可以在空间复杂度和时间复杂度很小的情况下求出1-101110了
然后对于区间和的修改 又利用每个小区间向上转移 修改了大区间的和
- 树状数组基础及运用
- 数组的基础及运用
- 树状数组运用
- 树状数组简单运用 hdu1166
- 树状数组的基本运用
- 基础树状数组
- 树状数组基础
- 基础树状数组
- 树状数组基础
- 树状数组基础
- HUD_1556_树状数组基础
- poj 3067 树状数组的基本运用
- 树状数组的两种运用
- mule基础及运用
- Number sequence 树状数组基础
- codevs树状数组基础练习
- hdu1166及树状数组模板
- 树状数组 模版 及 解释
- Linux CentOS乱码
- 每日英语阅读(十五)
- [UVA1331]最大面积最小三角形剖分
- PDF Expert For Mac v2.2.2中文版
- android中listview卡顿的终极原因解析
- 树状数组基础及运用
- 批量数据导入Redis(Mass Insertion)
- 活字格企业 Web 应用生成器新手上路指南
- 早起工作
- 递归的两种思路
- Writing a Linux Kernel Module — Part 2: A Character Device
- 动态规划9:变态跳台问题
- java创建对象的方式
- Android之Adapter用法总结