【模板】一维树状数组

ACM模板


目录

      • 聊聊前缀和
      • 什么是树状数组?
      • 树状数组相关操作
      • 局限性
      • 差分在树状数组中的应用
        • 区间更新、单点查询
        • 区间更新、区间查询
      • 树状数组应用

聊聊前缀和

比如数组

int a[7]={1,2,3,4,5,6,7}

如果需询问数组从第l个数到第r个数的和暴力做法时间复杂度为O(n)O(n)O(n)

不过我们可以预处理一个前缀和数组

int b[7]={1,3,6,10,15,21,28}

比如要询问[l,r]区间的和我们可以这样做b[r]-b[l-1]这也时间复杂度为O(1)O(1)O(1)

但是问题来了,如果我们要既要修改数组中元素的值,有要进行上述区间查询操作呢?

我们发现每次我们修改原数组中元素的值时间复杂度为O(1)O(1)O(1)但是如果修改前缀和数组中元素的值时间复杂度将会退化到O(n)O(n)O(n)

总结一下:

数组修改元素的值时间复杂度区间求和时间复杂度
原数组O(1)O(n)
前缀和数组O(n)O(1)

我们可以发现如果需要单点更新区间查询两种操作时间复杂度都是O(n)O(n)O(n)

什么是树状数组?

树状数组是一种便于进行单点更新区间查询的数据结构

树状数组相关操作

  1. 二进制中最后一个1——lowbitlowbitlowbit
   int lowbit(int x){return x&-x;}
  1. 单点更新

    我们对数组位置为x的元素加上c

   //树状数组为tree,数组元素个数为n,数组下标从0开始void add(int x,int c){for(;x<=n;x+=lowbit(x)) tree[x]+=c;}
  1. 区间求和
  //求出[1,x]数组中的总和即前缀和int sum(int x){int res=0;for(;x;x-=lowbit(x)) res+=tree[x];return res;}

局限性

我们很容易发现上述树状数组只适用于单点更新区间查询,但是如果是区间修改单点查询好像力不从心

差分在树状数组中的应用

告诉你个好消息如果有差分的介入,那么树状数组可以进行区间更新单点查询当然也可以进行更厉害的区间更新区间查询

区间更新、单点查询

我们把tree[]tree[]tree[]数组构造成一个差分数组还是看题吧

题目

给定长度为N的数列A,然后输入M行操作指令。

第一类指令形如“C l r d”,表示把数列中第l~r个数都加d。

第二类指令形如“Q X”,表示询问数列中第x个数的值。

对于每个询问,输出一个整数表示答案。

输入格式

第一行包含两个整数N和M。

第二行包含N个整数A[i]。

接下来M行表示M条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=100010;
ll tree[N];
int n,m;
int lowbit(int x) 
{return x&-x;
}
void add(int x,int c)
{for(;x<=n;x+=lowbit(x)) tree[x]+=c;
}
ll sum(int x)
{int res=0;for(;x;x-=lowbit(x)) res+=tree[x];return res;
}
int main()
{cin>>n>>m;for(int i=1;i<=n;i++){int a;cin>>a;add(i,a);add(i+1,-a);}while(m--){char t;cin>>t;if(t=='Q'){int x;cin>>x;cout<<sum(x)<<endl;}else{int a,b,c;cin>>a>>b>>c;add(a,c);add(b+1,-c);}}return 0;
}

我们可以发现对于上述代码即在建树的过程中建成差分树的形式即可

区间更新、区间查询

原数组a[],对于区间更新我们可以维护一个差分数组b[]

如果我们维护数组a的前缀和我们可以发现有下面等式:
∑i=1xai=∑i=1x∑j=1ibi=∑i=1x(x−i+1)bi\sum_{i=1}^x a_i=\sum_{i=1}^x\sum_{j=1}^i b_i=\sum_{i=1}^x(x-i+1)b_i i=1xai=i=1xj=1ibi=i=1x(xi+1)bi
变换一下:
∑i=1xai=(x+1)∑i=1xbi−∑i=1xbi×i\sum_{i=1}^x a_i=(x+1)\sum_{i=1}^x b_i-\sum_{i=1}^x b_i×i i=1xai=(x+1)i=1xbii=1xbi×i

于是我们可以维护两个差分树状数组tree1[]tree1[]tree1[]维护$ bi、、 tree2[]维护维护i*bi$

给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。

2、“Q l r”,表示询问 数列中第 l~r 个数的和。

对于每个询问,输出一个整数表示答案。

输入格式

第一行两个整数N,M。

第二行N个整数A[i]。

接下来M行表示M条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>using namespace std;typedef long long ll;const int N=100010;int n,m;
ll tree1[N],tree2[N];  //维护b[i]  维护i*b[i]
int lowbit(int x)
{return x&-x;
}void add(ll tree[],int x,ll c)
{for(;x<=n;x+=lowbit(x)) tree[x]+=c;
}ll sum(ll tree[],int x)
{ll res=0;for(;x;x-=lowbit(x)) res+=tree[x];return res;
}
ll prefix_sum(int x)
{return (x+1)*sum(tree1,x)-sum(tree2,x);
}int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){int a;scanf("%d",&a);add(tree1,i,a);add(tree1,i+1,-a);add(tree2,i,1ll*i*a);add(tree2,i+1,-1ll*(i+1)*a);}while(m--){char t;int l,r;cin>>t>>l>>r;if(t=='Q'){scanf("%d%d",&l,&r);cout<<prefix_sum(r)-prefix_sum(l-1)<<endl;}else{int d;scanf("%d",&d);add(tree1,l,d),add(tree1,r+1,-d);add(tree2,l,l*d),add(tree2, r+1,-1ll*(r+1)*d);}}return 0;
}

树状数组应用

  1. 区间更新区间查询

  2. 逆序对:首先有一种求逆序对的方法:开一个数组cnt[n]​然后遍历数组中的每一个数,在cnt[]数组中留下标记:比如数组中第i个元素为x,那就cnt[x]=1,所谓逆序即:我比你先出现而且比你大,对于上述例子所谓比你大即在[x+1,n]这个区间中的值,所谓比你先出现即在第i-1次遍历时被标记过。转化一下相当于求cntcntcnt数组中[x+1,n]区间内的和

  3. 第k小的数

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

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

相关文章

牛客题霸 单链表的选择排序 C++题解/答案

牛客题霸 单链表的选择排序 C题解/答案 题目描述 给定一个无序单链表&#xff0c;实现单链表的选择排序(按升序排序)。 题解&#xff1a; 不可能手写排序&#xff0c;这辈子不可能手写排序。。 基础的链表操作&#xff0c;将链表内的数据存到vector内&#xff0c;然后用sor…

牛客练习赛71E-神奇的迷宫【点分治,NTT】

正题 题目链接:https://ac.nowcoder.com/acm/contest/7745/E 题目大意 给出nnn个点的一棵树&#xff0c;每个点有一个选择权重aia_iai​&#xff08;有ai∑i1nai\frac{a_i}{\sum_{i1}^na_i}∑i1n​ai​ai​​的概率被选择&#xff09;。 然后有一个序列www。随机选择两次点&…

使用C#把Tensorflow训练的.pb文件用在生产环境

训练了很久的Tf模型&#xff0c;终于要到生产环境中去考验一番了。今天花费了一些时间去研究tf的模型如何在生产环境中去使用。大概整理了这些方法。继续使用分步骤保存了的ckpt文件这个貌似脱离不了tensorflow框架&#xff0c;而且生成的ckpt文件比较大&#xff0c;发布到生产…

OpenJudge1043 树上游戏(换根dp+细节处理)

树上游戏 给定一棵 nnn 个节点的树&#xff0c;点从 111 到 nnn 编号&#xff0c;点有点权&#xff0c;边有边权&#xff0c; Alice\text{Alice}Alice 和 Bob\text{Bob}Bob 两人在做游戏。 棋子以某一个点 sss 为起点&#xff0c;玩家移动该棋子&#xff0c;有以下两条规则&a…

牛客题霸 转圈打印矩阵 C++题解/答案

牛客题霸 转圈打印矩阵 C题解/答案 题目描述 给定一个整型矩阵matrix&#xff0c;请按照顺时针转圈的方式打印它。 示例1 输入 复制 [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]] 返回值 复制 [1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10] 题解&#xff1a; 题意很明确…

【招聘(上海)】东方财富证券招聘.net开发

东方财富证券&#xff1a;东方财富网(深创&#xff1a;300059)旗牌照齐全证券公司&#xff0c;极具互联网基因的券商。.Net服务端开发工程师/.Net前端开发工程师[职位介绍]服务端&#xff1a;开户、交易及资讯系统的后端接口服务(Asp.Net WebApi)开发&#xff1b;服务端&#x…

2020牛客NOIP赛前集训营-提高组(第三场)C-牛半仙的妹子Tree【虚树,最短路】

正题 题目链接:https://ac.nowcoder.com/acm/contest/7609/C 题目大意 给出nnn个点的一棵树&#xff0c;mmm个时刻各有一个操作 标记一个点&#xff0c;每个点被标记后的每一个时刻会标记掉周围的点。删去所有点的标记询问一个点是否有标记 解题思路 考虑没有二操作怎么搞&…

codeforces773 D. Perishable Roads(思维+最短路)

D. Perishable Roads 题意简述&#xff1a; 一个 nnn 个点的完全图 以 iii 为根节点时 询问 能构造的树的 ∑d(x)\sum d(x)∑d(x) 最小是多少。 d(x)d(x)d(x)&#xff1a; xxx 到根节点边权值最小值 MOONPIE题解 首先有一个显而易见的错误贪心&#xff1a; 不妨假设以root\t…

牛客题霸 两数之和C++题解/答案

牛客题霸 两数之和 C题解/答案 题目描述 给出一个整数数组&#xff0c;请在数组中找出两个加起来等于目标值的数&#xff0c; 你给出的函数twoSum 需要返回这两个数字的下标&#xff08;index1&#xff0c;index2&#xff09;&#xff0c;需要满足 index1 小于index2.。注意&…

P3244-[HNOI2015]落忆枫音【dp】

正题 题目链接:https://www.luogu.com.cn/problem/P3244 题目大意 给出一个DAG\text{DAG}DAG&#xff0c;保证111可以到达所有点。然后再加入一条边&#xff08;之后不一定是DAG\text{DAG}DAG&#xff09;。 求有多少棵以111为根的外向生成树。 1≤n≤105,1≤m≤21051\leq n…

EF Core 实现多租户

SAAS 和多租户SaaS(软件及服务)区别于其他应用程序的主要特征就是能够使客户在使用应用程序时按照使用量付费。他们不需要为软件购买许可&#xff0c;也不需要安装、托管和管理它。这方面的操作全部由提供 SaaS 软件的组织负责。多租户是实现 SaaS 的关键因素, 它可以让多个企业…

P3246 [HNOI2016]序列(莫队+单调栈+ST表)

[HNOI2016]序列 Tea神题解 Kelin神题解 对于莫队算法最主要的是如何快速算出[l,r]→[l,r1][l,r]\to[l,r1][l,r]→[l,r1]对答案的贡献的变化。 当询问区间发生上述变化时[l,r]→[l,r1][l,r]\to [l,r1][l,r]→[l,r1]不难发现子区间增加这些&#xff1a;[l,r1],[l1,r1],…,[r,r1…

P6672-[清华集训2016]你的生命已如风中残烛【结论】

正题 题目链接:https://www.luogu.com.cn/problem/P6672 题目大意 长度为mmm的序列aaa&#xff0c;有nnn个数字不是000&#xff0c;其他m−nm-nm−n个是000。要求重排后有多少方案满足 ∀x,∑i1xai≥i\forall x,\sum_{i1}^xa_i\geq i∀x,i1∑x​ai​≥i 其中m∑i1naim\sum_{i…

牛客题霸 反转链表 C++题解/答案

题目描述 输入一个链表&#xff0c;反转链表后&#xff0c;输出新链表的表头。 示例1 输入 复制 {1,2,3} 返回值 复制 {3,2,1} 题解&#xff1a; 如果用偷懒的方法&#xff0c;可以用vector来存链表内容&#xff0c;然后来个翻转&#xff08;vector自带&#xff09;即可 但是…

【.NET Core项目实战-统一认证平台】第五章 网关篇-自定义缓存Redis

上篇文章【.NET Core项目实战-统一认证平台】第四章 网关篇-数据库存储配置&#xff08;2&#xff09;我们介绍了2种网关配置信息更新的方法和扩展Mysql存储&#xff0c;本篇我们将介绍如何使用Redis来实现网关的所有缓存功能&#xff0c;用到的文档及源码将会在GitHub上开源&a…

P5934-[清华集训2012]最小生成树【最小割】

正题 题目链接:https://www.luogu.com.cn/problem/P5934 题目大意 给出nnn个点mmm条边的一张图&#xff0c;再加入一条边(u,v,L)(u,v,L)(u,v,L)求至少删掉多少条边可以使得这条边即在最小生成树上又在最大生成树上。 1≤n≤2104,1≤m≤21051\leq n\leq 2\times 10^4,1\leq m\…

广州.net俱乐部12月份ABP框架活动场地征集、志愿者征集、合作讲师\副讲师征集...

大家好&#xff0c;我在<被低估的.net(上) - 微软MonkeyFest 2018广州分享会活动回顾>一文中提到&#xff0c;我将在12月份搞一场ABP框架活动&#xff0c;现向大家征集活动场地、志愿者、合作讲师\副讲师。活动课程标题是&#xff1a;如何用ABP框架快速完成项目这是内容大…

4152. [AMPPZ2014]The Captain(稠密图最短路)

4152. [AMPPZ2014]The Captain 显然稠密图的边数时n2n^2n2量级&#xff0c;我们不可能把所有边建立出来&#xff0c;这时候通常寻求一些性质详细见【论题选编】稠密图最短路 针对本题我们可以先这样考虑&#xff0c;假设每个点有且只有一维信息&#xff0c;那么任意两点之间的…

牛客题霸 二分查找 C++题解/答案

牛客题霸 二分查找 C题解/答案 题目描述 请实现有重复数字的有序数组的二分查找。 输出在数组中第一个大于等于查找值的位置&#xff0c;如果数组中不存在这样的数&#xff0c;则输出数组长度加一。 示例1 输入 复制 5,4,[1,2,4,4,5] 返回值 复制 3 题解&#xff1a; 二分模…

CF1446F-Line Distance【计算几何,树状数组,二分】

正题 题目链接:https://www.luogu.com.cn/problem/CF1446F 题目大意 给出nnn个点&#xff0c;求所有点对构成的直线中与原点距离第kkk小的距离 2≤n≤105,1≤k≤n(n−1)22\leq n\leq 10^5,1\leq k\leq \frac{n(n-1)}{2}2≤n≤105,1≤k≤2n(n−1)​ 解题思路 二分还是挺显然的…