树状数组学习总结

news2024/11/28 9:33:13

今天本初中生蒟蒻学习了一下 树状数组 \color{red}{树状数组} 树状数组,总结一下~~~

树状数组的实现

功能简介

  • 快速求前缀和( O ( l o g 2 n ) \color{purple}{O(log_2n)} O(log2n)
  • 修改某一个数( O ( l o g 2 n ) \color{green}{O(log_2n)} O(log2n)

树状数组图示

树状数组其实就是如图所建立的~~~


下面引入一个函数——lowbit

lowbit(x)是x的二进制表达式中最低位的1所对应的值。

例如:

  1. l o w b i t ( 6 ) lowbit(6) lowbit(6)
    6的二进制为 ( 110 ) 2 (110)_2 (110)2 l o w b i t ( 6 ) = ( 10 ) 2 = 2 lowbit(6)=(10)_2=2 lowbit(6)=(10)2=2
  2. l o w b i t ( 8 ) lowbit(8) lowbit(8)
    8的二进制为 ( 1000 ) 2 (1000)_2 (1000)2 l o w b i t ( 8 ) = ( 1000 ) 2 = 8 lowbit(8)=(1000)_2=8 lowbit(8)=(1000)2=8

代码 \color{blue}{代码} 代码

int lowbit(int x)
{
    return x & -x;
}

知道这个函数之后,我们再来看这张图~~~
对于第一行的数字, l o w b i t 之后都等于 ( 1 ) 2 \color{green}{lowbit之后都等于(1)_2} lowbit之后都等于(1)2
对于第二行的数字, l o w b i t 之后都等于 ( 10 ) 2 \color{red}{lowbit之后都等于(10)_2} lowbit之后都等于(10)2
对于第三行的数字, l o w b i t 之后都等于 ( 100 ) 2 \color{purple}{lowbit之后都等于(100)_2} lowbit之后都等于(100)2
… \dots

这就是这张图的神秘之处~~~


快速求前缀和

我们再来观察这张图

如果我们想求 C 8 C_8 C8
那么 C 8 = A 8 + C 7 + C 6 + C 4 C8=A_8+C_7+C_6+C_4 C8=A8+C7+C6+C4
然后我们看一下这3个数7,6,4
7 − l o w b i t ( 7 ) ( 1 ) = 6 \color{orange}{7-lowbit(7)(1)=6} 7lowbit(7)(1)=6
6 − l o w b i t ( 6 ) ( 10 ) = 4 \color{pink}{6-lowbit(6)(10)=4} 6lowbit(6)(10)=4

综上所述:
C x = C x − l o w b i t ( x ) + C x − l o w b i t ( x ) − l o w b i t ( x − l o w b i t ( x ) ) + ⋯ + A x \color{red}{C_x=C_{x-lowbit(x)} + C_{x-lowbit(x) - lowbit(x-lowbit(x))+\dots+A_x}} Cx=Cxlowbit(x)+Cxlowbit(x)lowbit(xlowbit(x))++Ax

代码 \color{green}{代码} 代码

int sum(int x)
{
    int res = 0;
    for (int i = x; i; i -= lowbit(i)) res += tr[i]; //tr为我们的树状数组

    return res;
}

修改某一个数

还是这张图~~~

假如我们要修改的是C1,让他加上10
那么我们看一下他需要更新的点: C 1 , C 2 , C 4 , C 8 , C 16 C_1,C_2,C_4,C_8,C_{16} C1,C2,C4,C8,C16
再来看看他们的性质:
1 + l o w b i t ( 1 ) ( 1 ) = 2 \color{orange}{1+lowbit(1)(1)=2} 1+lowbit(1)(1)=2
2 + l o w b i t ( 2 ) ( 10 ) = 4 \color{pink}{2+lowbit(2)(10)=4} 2+lowbit(2)(10)=4
4 + l o w b i t ( 4 ) ( 100 ) = 8 \color{green}{4+lowbit(4)(100)=8} 4+lowbit(4)(100)=8
8 + l o w b i t ( 8 ) ( 1000 ) = 16 \color{blue}{8+lowbit(8)(1000)=16} 8+lowbit(8)(1000)=16

综上所述: 对于每一个 C x + l o w b i t ( x ) 都加上所要增加的数 ,注意: x 每次让其等于 x + l o w b i t ( x ) \color{red}{对于每一个C_{x+lowbit(x)}都加上所要增加的数},注意:x每次让其等于x+lowbit(x) 对于每一个Cx+lowbit(x)都加上所要增加的数,注意:x每次让其等于x+lowbit(x)

代码点这里! \color{brown}{代码点这里!} 代码点这里!

void add(int x, int val) //val为要加上的值
{
    for (int i = x; i <= n; i += lowbit(i)) tr[i] += val; //tr是树状数组
}

树状数组的应用

例题1——楼兰图腾

题目描述 \color{blue}{题目描述} 题目描述

在完成了分配任务之后,西部 314 来到了楼兰古城的西部。

相传很久以前这片土地上(比楼兰古城还早)生活着两个部落,一个部落崇拜尖刀(V),一个部落崇拜铁锹(),他们分别用 V 的形状来代表各自部落的图腾。

西部 314 在楼兰古城的下面发现了一幅巨大的壁画,壁画上被标记出了 n n n 个点,经测量发现这 n n n 个点的水平位置和竖直位置是两两不同的。

西部 314 认为这幅壁画所包含的信息与这 n n n 个点的相对位置有关,因此不妨设坐标分别为 ( 1 , y 1 ) , ( 2 , y 2 ) , … , ( n , y n ) (1,y_1),(2,y_2),…,(n,y_n) (1,y1),(2,y2),,(n,yn),其中 y 1 ∼ y n y_1∼y_n y1yn 1 1 1 n n n 的一个排列。

西部 314 打算研究这幅壁画中包含着多少个图腾。

如果三个点 ( i , y i ) , ( j , y j ) , ( k , y k ) i,y_i),(j,y_j),(k,y_k) i,yi),(j,yj),(k,yk) 满足 1 ≤ i < j < k ≤ n 1≤i<j<k≤n 1i<j<kn y i > y j , y j < y k y_i>y_j,y_j<y_k yi>yj,yj<yk,则称这三个点构成 V 图腾;

如果三个点 ( i , y i ) , ( j , y j ) , ( k , y k ) (i,y_i),(j,y_j),(k,y_k) (i,yi),(j,yj),(k,yk) 满足 1 ≤ i < j < k ≤ n 1≤i<j<k≤n 1i<j<kn y i < y j , y j > y k y_i<y_j,y_j>y_k yi<yj,yj>yk,则称这三个点构成 图腾;

西部 314 想知道,这 n n n 个点中两个部落图腾的数目。

因此,你需要编写一个程序来求出 V 的个数和 的个数。

输入格式

第一行一个数 n n n。第二行是 n n n 个数,分别代表 y 1 , y 2 , … , y n y1,y2,…,yn y1y2,,yn

输出格式

两个数,中间用空格隔开,依次为 V 的个数和 的个数。

数据范围

对于所有数据, n ≤ 200000 n≤200000 n200000,且输出答案不会超过 i n t 64 int64 int64
y 1 ∼ y n y_1∼y_n y1yn 1 1 1 n n n 的一个排列。

输入样例:

5
1 5 3 2 4

输出样例:

3 4

思路 \color{blue}{思路} 思路

答题思路是求出每个点左边比他高,和右边比他高的个数,相乘即使V
再求出每个点左边比他低,和右边比他低的个数,相乘即使

本题可以用树状数组来做,我们可以把纵坐标看做树状数组的下标。

即,在这个图中 C x C_x Cx表示为x及比x低的点的个数
所以对于每次插入一个点时,我们都让当前点及往上的点都加1.
这样我们在求一个每一个点的V数时:
个数就是 ( s u m ( n ) − s u m ( a i ) ) × ( n − a [ i ] − s u m ( n ) + s u m ( a i ) ) \color{purple}{个数就是(sum(n) - sum(a_i))\times (n - a[i] - sum(n) + sum(a_i))} 个数就是(sum(n)sum(ai))×(na[i]sum(n)+sum(ai))
注:因为我们在加1的时候算上了当前点,而题目中问的是比 a i a_i ai低的点,不包括 a i a_i ai,所以我们这里用前缀和思想 s u m ( n ) − s u m ( a i ) sum(n) - sum(a_i) sum(n)sum(ai),而不是 s u m ( n ) − s u m ( a i − 1 ) sum(n)-sum(a_i-1) sum(n)sum(ai1)
我们在求一个每一个点的数时:
个数就是 s u m ( a i − 1 ) × ( a [ i ] − 1 − s u m ( a i − 1 ) ) \color{green}{个数就是sum(a_i - 1)\times (a[i] - 1 - sum(a_i-1))} 个数就是sum(ai1)×(a[i]1sum(ai1))
注:这里减1是因为如果是 s u m ( a i ) sum(a_i) sum(ai)就会算上 a i a_i ai这个点,减1就不会了


代码 \color{blue}{代码} 代码

#include <iostream>
#include <cstring>
#include <algorithm>
#define int long long

using namespace std;

const int N = 2e5 + 10;

int n;
int a[N];
int high[N], low[N];
int tr[N];

int lowbit(int x)
{
    return x & -x;
}

void add(int x, int val)
{
    for (int i = x; i <= n; i += lowbit(i)) tr[i] += val;
}

int sum(int x)
{
    int res = 0;
    for (int i = x; i; i -= lowbit(i)) res += tr[i];

    return res;
}

signed main()
{
    cin >> n;
    
    for (int i = 1; i <= n; i ++)
        cin >> a[i];
    
    int r1 = 0, r2 = 0;
    for (int i = 1; i <= n; i ++ )
    {
        high[i] = sum(n) - sum(a[i]);
        low[i] = sum(a[i] - 1);
        r1 += high[i] * (n - a[i] - high[i]);
        r2 += low[i] * (a[i] - 1 - low[i]);
        add(a[i], 1);
    }
    
    cout << r1 << " " << r2 << endl;
}

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

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

相关文章

SpringBoot+原生awt,实现花花绿绿的图形验证码

图形验证码是用于验证用户身份的一种方式&#xff0c;通常在网站注册、登录或进行某些敏感操作时会使用。它通过展示一个包含随机字符或数字的图形&#xff0c;要求用户输入相应的字符或数字来证明其为真人而非机器人。图形验证码能有效地防止机器人攻击和恶意注册行为&#xf…

Excel·VBA自动生成日记账的对方科目

如图&#xff1a;根据日记账/序时账的日期、凭证号为一组&#xff0c;按借贷方向生成相反的科目&#xff0c;并写入H列。可能存在一对一、一对多、多对多等情况的账目 目录 数组法遍历、判断、写入测试结果 多对多问题处理测试结果 数组法遍历、判断、写入 适用日期凭证号连续…

HTTPS的加密流程——巨详细!

文章目录 前言HTTPS的工作过程引入对称加密引入非对称加密引入证书完整的加密流程总结 前言 HTTPS 也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层. HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现一些被篡改的情况. 比如&#xff1a;臭…

民宿预订系统的设计与实现(ASP.NET,SQLServer)

这个民宿预订系统是由第三方的运营公司来运营&#xff0c;他提供了一个民宿和客户都使用的一个信息平台&#xff0c;民宿注册之后把自己的民宿信息发布到网站平台上&#xff0c;然后发布自己的房间信息&#xff0c;打折信息等供客户查看和选择。客户可以在网站平台上查看民宿信…

深度学习:大模型的正则化

l1l2正则和dropout正则化[https://youzipi.blog.csdn.net/article/details/75307522] LN和BN归一化 [深度学习:批归一化Batch Normalization] 主流大模型使用的Normalization主要有三类,分别是Layer Norm,RMS Norm,以及Deep Norm。 Post-Norm和Pre-Norm 根据Normalizat…

网工内推 | 快手、瑞芯微招运维,思科、红帽认证优先

01 快手 招聘岗位&#xff1a;IT系统运维 职责描述&#xff1a; 1、负责IT基础架构运维体系的建设和优化改进&#xff1b; 2、负责IT核心基础服务&#xff08;如DNS、负载均衡、容器&#xff09;的架构设计、平台建设和运维&#xff1b; 3、负责IT内部日志系统、监控系统、报警…

SpringCloud微服务框架(通俗易懂,一秒上手)

&#x1f381;&#x1f381;资源&#xff1a;https://pan.baidu.com/s/1zRmwSvSvoDkWh0-MynwERA&pwd1234 SpringCloud微服务框架 &#xff08;一&#xff09;认识微服务服务架构演变SpringCloud &#xff08;二&#xff09;微服务拆分案例服务拆分服务间调用 &#xff08;三…

ROS:订阅者Subscriber的编程实现(C++)

目录 一、话题模型二、创建功能包三、创建Subscriber代码四、编译代码五、运行 一、话题模型 图中&#xff0c;我们使用ROS Master管理节点。 有两个主要节点&#xff1a; Publisher&#xff0c;名为Turtle Velocity&#xff08;即海龟的速度&#xff09; Subscriber&#xff0…

Rocketmq面试(一) Rocketmq同一个消费组订阅不同的Tag,会有什么问题?

先说结果&#xff1a;会造成数据丢失 再说依据&#xff1a; RocketMQ要求同一个消费者组内的消费者必须订阅关系一致&#xff0c;如果订阅关系不一致会出现消息丢失的问题。 官网入口&#xff1a;订阅关系一致 | RocketMQ 不想看官网的&#xff0c;直接看结论 什么叫订阅关…

复杂SQL实践-MYSQL

MySQL 8.0窗口函数 MySQL从8.0版本开始支持窗口函数。 窗口函数总体上可以分为序号函数, 分布函数, 前后函数, 首尾函数和其他函数。 描述 题目&#xff1a;现在运营想要查看用户在某天刷题后第二天还会再来刷题的平均概率。请你取出相应数据。 示例1 drop table if exist…

对远程http服务的拨测体验

背景&#xff1a; 过程是这样的&#xff0c;需要与合作方数据进行交互&#xff08;肯定是不允许直接连对方数据源的&#xff09;&#xff0c;对方提供了两台server&#xff0c;后端同事在server上面作了proxy搭建了桥接的应用&#xff08;两台server没有公网ip&#xff0c;通过…

Eclipse 教程Ⅹ

本次内容会涉及到Eclipse 重构菜单、Eclipse 添加书签和Eclipse 任务管理&#xff0c;老规矩&#xff0c;直接开始吧&#xff01; Eclipse 重构菜单 使用Eclipse重构 在项目开发中我们经常需要修改类名&#xff0c;但如果其他类依赖该类时&#xff0c;我们就需要花很多时间去…

机器学习模型的生命周期

动动发财的小手&#xff0c;点个赞吧&#xff01; 您的模型如何变化&#xff1f;Source[1] 诞生 当我们构建、训练、拟合或估计我们的模型时&#xff0c;这些数字工具就诞生了。这个阶段几乎从拥有分析目标、数据、计算机、算法以及数据科学家现在已经非常了解的其他一切开始。…

Linux [权限]

Linux 权限 Linux用户分类切换成root方法例子 切换成普通用户方法例子 短暂提权 什么是权限理论知识展示区域 修改权限(1)修改文件属性1. 采用 w/r/x的形式2. 采用八进制的形式 (2)修改身份1. 修改拥有者2. 修改所属组3. 修改拥有者 && 所属组 问题区问题1问题2问题3 L…

实在智能携手各高校打造高端数字化技能教育平台

百年大计&#xff0c;教育为本。2021年在《教育部办公厅关于印发高等职业教育专科英语、信息技术课程标准&#xff09;的通知中把机器人流程自动化列入专科信息技术课程学习计划之中&#xff0c;进一步明确职业教育中数字化人才发展方向。 一、为什么要大力培养数字化人才&…

毕业5年的同学突然告诉我,他已经是年薪30W的自动化测试工程师,我愣住了...

作为一名程序员&#xff0c;都会对自己未来的职业发展而焦虑。一方面是因为IT作为知识密集型的行业&#xff0c;知识体系复杂且知识更新速度非常快&#xff0c;“一日不学就会落后”。 另外一方面&#xff0c;IT又是劳动密集型的行业&#xff0c;不仅业人员多&#xff0c;而且个…

随机梯度下降法

梯度下降法有两个比较大的缺点&#xff1a; --计算花时间 --容易陷入局部最优解 比如以下形状的函数&#xff0c;最优解取决于初始值的选取。 梯度下降法的表达式如下&#xff0c;这个表达式使用了所有训练数据的误差&#xff1a; 随机梯度下降法表达式&#xff1a; 在随机梯…

Cmake学习记录(九)--使用Cmake交叉编译.so库

文章目录 一、前言二、相关代码三、参考链接 一、前言 目前Android编译.so的话使用Android Studio比较简单&#xff0c;但是有时候时候Android Studio的话还需要创建一个Android的项目&#xff0c;这里记录下脱离Android Studio单纯使用Cmake和C开发工具Clion(或者其他的开发工…

Prometheus+grafana+node_exporter环境搭建

原理&#xff1a; node_exporter采集数据&#xff0c;Prometheus通过配置文件Prometheus.yml配置node_exporter信息获取采集到的数据并做展示&#xff0c;grafana将Prometheus作为数据源展示node_exporter采集到的数据 拓扑图 问题&#xff1a; 1&#xff09;为什么不直接用…

万众瞩目的Nautilus Chain即将上线主网,生态正式起航

Zebec Protocol 是以流支付为定位 Web3 生态&#xff0c;该生态旨在构建一个全新的支付方式&#xff0c;以进一步丰富加密支付场景&#xff0c;并推动加密支付的大规模采用&#xff0c;该生态此前在 Solans 生态中曾取得了十分亮眼的成绩。目前&#xff0c;Zebec Protocol 正在…