树状数组(瞎bb) [树状数组]
Copyright:http://www.cnblogs.com/ZYBGMZL/
树状数组是一个利用一维数组和位运算组成的求解区间问题的高效数据结构,其构造如图所示

首先,我们要用它解决单点修改、区间查询的操作。
根据这张图我们建立一个数组bit[],下标就是图中显示的十进制数。bit[i]就表示了图中所示的一段区间的和,例如bit[6]=sum(5,6),bit[4]=sum(1,4)。
下标最大值为序列的长度n。
我们接下来要求一段序列中left到right的和,就可以转化为求sum(1,right)-sum(1,left)。
那么对于已知的x,怎么求sum(1,x)呢?

在这样一个栗子(上图)中,我们需要求得sum(1,6)的值,可以将其转化为求bit[6]+bit[4]。
显而易见,只要将6的二进制数0110的最低位1删去,就得到0100,对应了10进制的4。

再举一个栗子(如上图),我们想求sum(1,3)的值,只要求bit[2]+bit[3]就好了。
变化规律和上一个一样。(0011---->0010)

对于多段区间,也满足一样的规律(上图)。
我们总结,对于x,只要不断减去x中最低位的1,将得到的bit[x]相加就可以得到结果了。
用这样一个方法获取x的最低位1
x&-x
就得到了这样一个操作代码
int sum(int x){
int sum=;
while(x){
x+=bit[x];
x-=x&-x;
}
return sum;
}
查询的问题解决了,接下来要处理修改的操作了。

举个栗子,假如对3点进行加a的操作,在bit[3]修改的同时,bit[4]和bit[8]也要相应修改。
观察这3个数(3,4,8)的二进制数,可以发现,只要不断地加上其最低位的1,就可以完成操作了。
0011+0001=0100
0100+0100=1000
再对所得的数判断是否大于n即可。
于是我们得到了这样一个单点修改的操作代码。
void add(int x,int a){
while(x<=n){
bit[x]+=a;
x+=x&-x;
}
}
以上是树状数组操作最简单的模型,除此之外,树状数组还有区间修改、单点查询,以及区间修改、区间查询的功能。
区间修改、单点查询
//改段求点型操作 //b[i]表示区间1...i一共变化的量
int b[];
//原始数组
int a[]; void ADD(int x, int c)
{
for (int i=x; i>; i-=i&(-i))
b[i] += c;
} void add(int left,int right,int c){
if(left-1) ADD(left-,-c);
ADD(right,c);
} int SUM(int x)
{
int s = ;
for (int i=x; i<=n; i+=i&(-i))
s += b[i];
return s+a[x];
}
区间修改、区间查询
//改段求段型:
//这是最复杂的模型,需要两个辅助数组:B[i]表示a[1..i]到目前为止共被整体加了多少(和模型2中的一样)
//C[i]表示a[1..i]到目前为止共被整体加了多少的总和(或者说,C[i]=B[i]*i)。 //对于ADD(x, c),只要将B[x]加上c,同时C[x]加上c*x即可(根据C[x]和B[x]间的关系可得); //而ADD(x, c)操作是这样影响a[1..i]的和的:若x小于i,则会将a[1..i]的和加上x*c,
//否则(x>=i)会将a[1..i]的和加上i*c。也就是,a[1..i]之和 = B[i..N]之和 * i + C[1..i-1]之和。
//这样对于B和C两个数组而言就变成了“改点求段”(不过B是求后缀和而C是求前缀和)。
//另外,该模型中需要特别注意越界问题,即x=0时不能执行SUM_B操作和ADD_C操作。 //【1】修改操作:将A[l..r]之间的全部元素值加上c;
//ADD_B(r, c); ADD_C(r, c);
//if (l > 1) {ADD_B(l - 1, -c); ADD_C(l - 1, -c);}
//【2】求和操作:求此时A[l..r]的和。
//SUM(r) - SUM(l - 1)。 //B[i]表示区间1...i变化量
int B[];
//C[i]表示区间1...i变化量的总和,有c[i]=b[i]*i
int C[]; void ADD_B(int x, int c)
{
for (int i=x; i>; i-=i&(-i)) B[i] += c;
} void ADD_C(int x, int c)
{
for (int i=x; i<=n; i+=i&(-i)) C[i] += x * c;
} int SUM_B(int x)
{
int s = ;
for (int i=x; i<=n; i+=i&(-i)) s += B[i];
return s;
} int SUM_C(int x)
{
int s = ;
for (int i=x; i>; i-=i&(-i)) s += C[i];
return s;
} int SUM(int x)
{
if (x) return SUM_B(x) * x + SUM_C(x - ); else return ;
}
树状数组(瞎bb) [树状数组]的更多相关文章
- HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)
Weak Pair Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Tota ...
- 计蒜客 1460.Ryuji doesn't want to study-树状数组 or 线段树 (ACM-ICPC 2018 徐州赛区网络预赛 H)
H.Ryuji doesn't want to study 27.34% 1000ms 262144K Ryuji is not a good student, and he doesn't wa ...
- bzoj1901--树状数组套主席树
树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树
[题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...
- POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树
题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
[题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...
- BZOJ1901 - Dynamic Rankings(树状数组套主席树)
题目大意 给定一个有N个数字的序列,然后又m个指令,指令种类只有两种,形式如下: Q l r k 要求你查询区间[l,r]第k小的数是哪个 C i t 要求你把第i个数修改为t 题解 动态的区间第k ...
- bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 629[Submit][Stat ...
- [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】
题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...
随机推荐
- JQuery--Ajax 异步操作 动态添加节点 (新人试水,求支持)
异步操作动态添加节点,导致在代码中给添加的节点全局绑定事件或者获取元素无效,上代码: $(function () { var IP = '...'; // 页面中的默认编号起始值 和 公用IP前缀 s ...
- 刨根究底字符编码之十三——UTF-16编码方式
UTF-16编码方式 1. UTF-16编码方式源于UCS-2(Universal Character Set coded in 2 octets.2-byte Universal Character ...
- Vulkan Tutorial 14 Integration pipeline
操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 我们现在整合前几章节的结构体和对象创建图形管线!以下是我们现在用到的对象类型,作为一 ...
- php调用java
PHP调用JAVA方式 1. 背景 在开发招商银行信用卡分期付款功能过程中,在支付成功之后需要对银行的返回数据进行签名验证,因签名加密方式招商银行是不提供的,只提供了相应的JAVA验证类测试例 ...
- Windows下彻底卸载删除SQL Serever2012
在安装了SQL Server2012之后,当由于某些原因我们需要卸载它时,我们应该怎么操作呢?相信这个问题困扰着不少人,博主经过亲身实践之后,给大家提供这样一种方法. 第一步.在控制面板里面找到程序— ...
- javascript基础数据类型与引用类型
javascript一共有6种数据类型 有5种基本类型:Null,String Number,Boolean,Undefined 和一种引用类型Object 基础类型在内存中存在于栈空间中,例如 va ...
- Android 串口设置校验位、速率、停止位等参数
Android 串口通讯设置校验位.速率.停止位等参数 最近业余时间有个android项目需要和硬件进行通信,通讯方式都是通过串口,android串口通讯google有个开源的demo 和很多人一样我 ...
- windows下pycharm远程调试pyspark
参考http://www.mamicode.com/info-detail-1523356.html1.远端执行:vi /etc/profile添加一行:PYTHONPATH=$SPARK_HOME/ ...
- webdriver API中文文档
1.1 下载selenium2.0的lib包 http://code.google.com/p/selenium/downloads/list 官方UserGuide:http://seleniu ...
- Ext 常用组件解析
Ext 常用组件解析 Panel 定义&常用属性 //1.使用initComponent Ext.define('MySecurity.view.resource.ResourcePanel' ...