树状数组三种模型

树状数组在区间求和问题上有大用,其三种复杂度都比线段树要低很多……有关区间求和的问题主要有以下三个模型(以下设A[1..N]为一个长为N的序列,初始值为全0):

(1)“改点求段”型,即对于序列A有以下操作:

【1】修改操作:将A[x]的值加上c;

【2】求和操作:求此时A[l..r]的和。

这是最容易的模型,不需要任何辅助数组。树状数组中从x开始不断减lowbit(x)(即x&(-x))可以得到整个[1..x]的和,而从x开始不断加lowbit(x)则可以得到x的所有前趋。代码:

void ADD(int x, int c)
{
     for (int i=x; i<=n; i+=i&(-i)) a[i] += c;
}
int SUM(int x)
{
    int s = 0;
    for (int i=x; i>0; i-=i&(-i)) s += a[i];
    return s;
}

 

操作【1】:ADD(x, c);

操作【2】:SUM(r)-SUM(l-1)。

(2)“改段求点”型,即对于序列A有以下操作:

【1】修改操作:将A[l..r]之间的全部元素值加上c;

【2】求和操作:求此时A[x]的值。

这个模型中需要设置一个辅助数组B:B[i]表示A[1..i]到目前为止共被整体加了多少(或者可以说成,到目前为止的所有ADD(i, c)操作中c的总和)。

则可以发现,对于之前的所有ADD(x, c)操作,当且仅当x>=i时,该操作会对A[i]的值造成影响(将A[i]加上c),又由于初始A[i]=0,所以有A[i] = B[i..N]之和!而ADD(i, c)(将A[1..i]整体加上c),将B[i]加上c即可——只要对B数组进行操作就行了。
【首先对于每个数A定义集合up(A)表示{A, A+lowestbit(A), A+lowestbit(A)+lowestbit(A+lowestbit(A))...} 定义集合down(A)表示{A, A-lowestbit(A), A-lowestbit(A)-lowestbit(A-lowestbit(A)) ... , 0}。可以发现对于任何A<B,up(A)和down(B)的交集有且仅有一个数。
翻转一个区间[A,B](为了便于讨论先把原问题降为一维的情况),我们可以把down(B)的所有元素的翻转次数+1,再把down(A-1)的所有元素的翻转次数-1。而每次查询一个元素C时,只需要统计up(C)的所有元素的翻转次数之和,即为C实际被翻转的次数】

这样就把该模型转化成了“改点求点”型,只是有一点不同的是,SUM(x)不是求B[1..x]的和而是求B[x..N]的和,此时只需把ADD和SUM中的增减次序对调即可(模型1中是ADD加SUM减,这里是ADD减SUM加)。代码:
void ADD(int x, int c)
{
     for (int i=x; i>0; i-=i&(-i)) b[i] += c;
}
int SUM(int x)
{
    int s = 0;
    for (int i=x; i<=n; i+=i&(-i)) s += b[i];
    return s;
}

操作【1】:ADD(l-1, -c); ADD(r, c);

操作【2】:SUM(x)。

(3)“改段求段”型,即对于序列A有以下操作:

【1】修改操作:将A[l..r]之间的全部元素值加上c;

【2】求和操作:求此时A[l..r]的和。

这是最复杂的模型,需要两个辅助数组: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操作!代码:

void ADD_B(int x, int c)
{
     for (int i=x; i>0; 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 = 0;
    for (int i=x; i<=n; i+=i&(-i)) s += B[i];
    return s;
}
int SUM_C(int x)
{
    int s = 0;
    for (int i=x; i>0; i-=i&(-i)) s += C[i];
    return s;
}
inline int SUM(int x)
{
    if (x) return SUM_B(x) * x + SUM_C(x - 1); else return 0;
}

操作【1】:
ADD_B(r, c); ADD_C(r, c);
if (l > 1) {ADD_B(l - 1, -c); ADD_C(l - 1, -c);}
操作【2】:SUM(r) - SUM(l - 1)。

转载于:https://www.cnblogs.com/hujunzheng/articles/3968965.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531672.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php实现直播答题系统,直播答题解决方案

概述即构提供直播答题一站式解决方案&#xff0c;包括 Windows 主播端、移动 APP 端示例源代码(iOS、Android)。1 下载/体验地址由于直播答题场景需要主播端(推流、发题)和观众端(拉流、答题)配合使用&#xff0c;因此开发者需要同时下载这两端的软件。下载后&#xff0c;具体的…

poj 3486 A Simple Problem with Integers(树状数组第三种模板改段求段)

1 /*2 树状数组第三种模板&#xff08;改段求段&#xff09;不解释&#xff01; 不明白的点这里&#xff1a;here&#xff01;3 */4 #include<iostream>5 #include<cstring>6 #include<cstdio>7 #include<algorithm>8 #define N 1000059 us…

php路由类默认模块,微擎入口路由及其模块入口路由 - YangJunwei

一、微擎入口路由微擎有2个入口文件/web/index.php?csite&aentry/app/index.php?centry路由变量$controller $_GPC[c]; //web入口缺省值account&#xff0c;app入口home$action $_GPC[a]; //index.php入口文件开头$acl变量可配置默认方法$do $_GPC[do];不管$action是什…

matlab subs 慢,求助matlab程序计算速度过慢的原因

程序代码如下function [length]contactlength(x0)if x0>50||x0error:数据超出尺寸范围elsesyms xR300;%非球面顶点曲率半径c1/R;delta0.1;k-3.3;%非球面参数rb27;%半径y(-1*c*x.^2)./(1sqrt(1-(1k)*(c^2)*x.^2));dydiff(y);dy2diff(y,2);dyx0subs(dy,x0);dy2x0subs(dy2,x0);…

matlab r2010a教程,MATLAB教程R2010a(十二五)

第1章 基础准备及入门1.1 MATLAB的安装和工具包选择1.2 Desktop操作桌面的启动1.2.1 MATLAB的启动1.2.2 Desktop操作桌面简介1.3 Command Window运行入门1.3.1 Commancl Winelow指令窗简介1.3.2 最简单的计算器使用法1.3.3 数值、变量和表达式1.4 Command Window操作要旨1.4.1 …

java中解决组件重叠的问题(例如鼠标移动组件时)

java中解决组件覆盖的问题&#xff01; 有时候在移动组件的时候会出现两个组件覆盖的情况&#xff0c;但是你想让被覆盖的组件显示出来或者不被覆盖&#xff01;在设计GUI时已经可以定义组件的叠放次序了&#xff08;按摆放组件的先后顺序&#xff09;。 真正麻烦的是响应哪…

matlab桥梁受力计算公式,matlab桥梁计算

等级&#xff1a;文件 218KB格式 pdf内容简介 该文结合斜拉桥施工监控的工程实践&#xff0c;分析研究利用MATLAB 6&#xff0e;0神经网络算法&#xff0c;可实现模式识别和函数逼近&#xff0c;进行信号处理&#xff0c;利用人工智能进行自动控制及非线性预测等。斜拉桥智能施…

php自然排序法的比较过程,PHP中strnatcmp()函数“自然排序算法”进行字符串比较用法分析(对比strcmp函数)...

本文实例讲述了PHP中strnatcmp()函数“自然排序算法”进行字符串比较用法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;PHP中strnatcmp()函数使用"自然"算法来比较两个字符串(区分大小写)&#xff0c;通常在自然算法中&#xff0c;数字 2 小于数字 10。而…

2014 网选 5014 Number Sequence(异或)

1 /*2 题意&#xff1a;a, b两个序列&#xff0c;规定由[0, n]区间的数&#xff01;3 求 a[i] ^ b[i] 的和最大&#xff01; 4 5 思路&#xff1a;如果数字 n的二进制有x位&#xff0c; 那么一定存在一个数字m&#xff0c;使得n^m的所有二进制位6 都是1&am…

2014 网选 5007 Post Robot(暴力或者AC_自动机(有点小题大作了))

//暴力&#xff0c;从每一行的开始处开始寻找要查询的字符 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;char str[100005];int main(){while(gets(str)){for(int i0; str[i]; i)if(str[i]A){if(s…

java 如何放大动画图,Android仿微信图片放大动画

&#xff03;今年三月份直接上手做的android&#xff0c;代码写的不规范&#xff0c;有问题希望指出&#xff0c;谢谢(app数英)类似于微信 图片浏览的效果&#xff0c;我的做法是在两个activity A\B之间传递图片的位置信息思路&#xff1a;在activity A的list view上有一张图片…

2014 网选 5012 Dice(bfs模板)

1 /*2 题意&#xff1a;就是给定两个筛子&#xff0c;每个筛子上6个面&#xff0c;每个面的数字属于[1,6]&#xff0c; 且互不相同&#xff01;3 问a筛子最少经过按照题目规定的要求转动&#xff0c;达到和b筛子上下左右前后的数字相同&#xff01;4 5 思路&am…

matlab 神经网络dpi,基于DPI和BP神经网络的P2P流量识别研究

研究与开发 现代计算机 2019.04 上 文章编号&#xff1a;1007-1423(2019)10-0031-05 DOI&#xff1a;10.3969/j.issn.1007-1423.2019.10.007 基于 DPI 和 BP 神经网络的 P2P 流量识别研究 万建伟&#xff0c;胡勇 (四川大学电子信息学院&#xff0c;成都 610021) 摘要&#xff…

2014 网选 5011 Game(Nim游戏,数学题)

/*题意&#xff1a;Nim游戏&#xff01; 思路&#xff1a;通过异或&#xff0c;判断将n个数表示成二进制的形式之后&#xff0c;是否对应位的数字1 的个数是偶数&#xff01; */ #include<iostream> using namespace std;int main(){int n, x, s;while(cin>>n){s…

汉诺塔实践python,Python练习题11:汉诺塔实践

在终端输出如下信息--python在终端输出如下信息--python ???????????????????????????????????????????????????????????????????????????????????????????????? 描述 练习一…

oracle授权只读用户,Oracle创建只读用户(账号)的方法

第一步&#xff1a;创建用户(需要使用有dba管理员权限的用户创建一个新的用户&#xff0c;比如system)create user 用户名 identified by 密码 default tablespace 表空间;第二步&#xff1a;赋连接权限grant connect to 用户名;grant Resource to 用户名;权限分类&#xff1a;…

java中图片文件的传输及显示(Socket以及ServerSocket演示)

//客户端部分 package testSix;import java.awt.Graphics; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.util.Iterator;import javax.imageio.ImageIO; import …

oracle 表约束非空,oracle--约束(主键、非空、检查)

问题1:学号重复了&#xff0c;数据还可以插入成功使用主键约束&#xff1a;学号是唯一标识一条数据的&#xff0c;所以必须唯一且不能为空---(1)、在确定为主键的字段后添加 primary key关键字---(2)、在创建表的后面使用&#xff1a;constraints pk_表名_字段名 primary key(字…

先序,中序,后序线索二叉树

//后序线索&#xff0c;这种方法不容易想到 1 #include<iostream>2 #include<cstring>3 #include<cstdio>4 #include<algorithm>5 6 using namespace std;7 8 struct TREE{9 int val; 10 TREE *ch[2]; 11 TREE *thread;//该节点的线索的…

cdp备份适合oracle吗,备份系统建设中的四个认识误区,你有吗?

【摘要】本文总结了企业在备份建设中常见的四个认识误区。【作者】李志刚企业在备份建设中&#xff0c;主要的认识误区有以下几个&#xff1a;一、用双机、阵列复制等系统冗余替代数据备份双机双柜可实现服务器和存储的高可用性&#xff0c;保障业务持续运行&#xff0c;但绝不…