241. 楼兰图腾——树状数组

news2024/9/28 9:25:52

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

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

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

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

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

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

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

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

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

输入格式
第一行一个数 n。

第二行是 n 个数,分别代表 y1,y2,…,yn。

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

数据范围
对于所有数据,n≤200000,且输出答案不会超过 int64。
y1∼yn 是 1 到 n 的一个排列。

输入样例:
5
1 5 3 2 4
输出样例:
3 4

分析

  1. 当我们需要实现单点修改、区间查询,如果用普通的前缀和的话,查询O(1),修改后的话需要重新计算前缀和,那就又O(n)了,如果m次查询,那就O(m*n)的复杂度了,特殊情况肯定TLE;所以我们引入一种新的数据结构,就是树状数组,他的单点修改、区间查询都是O(logn)的复杂度
  2. 要学树状数组,一共三个函数,首先了解一个lowbit函数,他是求x的二进制序列中最低位的1加上其后面所有0所对应的十进制的值;比如:lowbit(8)=lowbit([1000])=2^3=8;可以使用x & -x来计算;
  3. add(x,c)函数就是将序列中第x个数(a[i])加上c,i从x开始,i 每次+=lowbit(i),然后向上更新,tr[i] += c;(改了一个点a[i],影响的是唯一的父节点,是一个单链路径,tr[i]结点的父结点为t[i + lowbit(x)])
  4. sum(x)函数是1到x位置的区间和,在这题sum就是查询x之前( 区间[1,x] )的元素出现次数之和,注意此题是查的次数,树状数组存的是出现次数的前缀和;
  5. 树状数组tr的含义:tr[N]相当于c[N],tr[i] =【i,lowbit(i)】,表示以i结尾,长度为lowbit(i)的区间和,这里是出现次数的前缀和;
  6. 然后这个题,先从左到右,V的个数就是,i从1到n枚举y=a[i],看看其左边有多少个数小于他,保存在low中;看看其左边有多少个数大于他,保存在gre中,然后把当前的y加入树状数组;最后计算完从左到右,然后清空树状数组,计算从右到左,(sum(n) - sum(y))就相当于从右到左的gre[i];那么当前yj=y时的V的方案数就是:左边比他大的个数 乘 右边比他大的个数;同样 ∧型也如此;
  7. 下面所有图片来源于acwing的一位大佬:AcWing 241. 楼兰图腾 作者: qiaoxinwei ;可以比较容易的理解add、sum操作的过程;而且链接里面有暴力O(n*n)的解法,思路也是很不错的,维护4个前缀数组,可以去参考;

此题解题思路:
在这里插入图片描述

一个序列的树形结构:
在这里插入图片描述

add(x,k)表示将序列中第x个数加上k,在整棵树上维护这个值,需要一层一层向上找到父结点,并将这些结点上的tr[x]值都加上k
在这里插入图片描述
sum(x):表示将查询序列前x个数的和
在这里插入图片描述
查询sum(7)的前缀和,需要从这个点向左上找到上一个结点,将加上其结点的值tr[i]。向左上找到上一个结点,只需要将下标 x -= lowbit(x),例如 7 - lowbit(7) = 6,6-lowbit(6)=4,不断向左上找;

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 200010;
int n;
int a[N];
int tr[N];//树状数组,相当于c,tr[i] =【i,lowbit(i)】,表示以i结尾,长度为lowbit(i)的区间和,这里是出现次数的前缀和
int low[N];//low[i]:i位置前面 小于a[i]的个数
int gre[N];//gre[i]:i位置前面 大于a[i]的个数

//求x的二进制序列中最低位的1所对应的值
int lowbit(int x) {
    return x & -x;
}

//自下而上更新,将序列中第x个数加上c,此题的c表示次数
void add(int x, int c) {
    for (int i = x; i <= n; i += lowbit(i))
        tr[i] += c;
}

//查询值为x的位置之前([1,x])的元素出现 次数 之和
LL sum(int x) {
    LL res = 0;
    for (int i = x; i; i -= lowbit(i))
        res += tr[i];
    return res;
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    //1. 从左向右统计比 a[i] 小的个数、大的个数
    for (int i = 1; i <= n; ++i) {
        int y = a[i];
        //已加入树状数组的数中,值为 y+1~n 有多少个数(比a[i]大的个数)
        gre[i] = sum(n) - sum(y);
        //已加入树状数组的数中,值为 1~y-1 有多少个数(比a[i]小的个数)
        low[i] = sum(y - 1);
        //将y加入树状数组,y出现一次
        add(y, 1);
    }
    //2. 从右向左统计比a[i]小的个数、大的个数
    LL ansA = 0, ansV = 0;//呈V、A型的个数
    memset(tr, 0, sizeof tr);
    for (int i = n; i > 0; --i) {
        int y = a[i];
        ansV += gre[i] * (sum(n) - sum(y));//a[i]左边大于a[i]个数 * 右边大于a[i]个数
        ansA += low[i] * sum(y - 1); //a[i]左边小于a[i]个数 * 右边小于a[i]个数
        //将y加入树状数组
        add(y, 1);
    }
    cout << ansV << " " << ansA;
    return 0;
}

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

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

相关文章

xv6 makefile详解

文章目录makefile语法格式生成qemu可执行文件生成kernel可执行文件生成kernel下的OBJSkernel.ldbuild OBJS_KCSANbuild initcode生成一个fs.img文件系统mkfs用户程序的编译配置工具makefile语法格式 makefile就是一个深搜的过程&#xff0c;最上面的语句是顶级目标&#xff0c…

python-函数、文件、异常、模块

目录 函数 返回值 函数传参 位置参数 关键字传参 缺省参数 不定长参数 匿名函数 文件操作 open 函数 异常 模块 导入模块 函数 返回值 return语句[表达式]退出函数&#xff0c;选择性地向调用方返回一个表达式。不带参数值的return语句返回None #定义函数 def a…

Ubuntu系统装机流程(显卡驱动、cuda、cudnn、搜狗输入法、anaconda、pycharm)

整体流程一、安装Ubuntu18.04系统二、安装显卡驱动三、安装Cuda四、安装Cudnn五、安装搜狗输入法六、安装Anaconda七、安装Pycharm社区版一、安装Ubuntu18.04系统 &#xff08;1&#xff09;实现用软碟通做好一个装有Ubuntu18.04的系统盘。 &#xff08;2&#xff09;打开电脑…

Jenkins自动发布到Docker部署服务器把Jar包打包成镜像并启动容器

《jenkins自动化发布到服务器并自动运行》 第1种方法&#xff1a;使用外部Jar包完成自动化部署&#xff08;简单方便&#xff09;&#xff0c;正式环境更新jar包时&#xff0c;备份一下旧的的jar包即可。 修改jenkins项目配置 Pre Steps 构建前清除旧的jar包&#xff0c;然后…

计算机网络原理第2章 物理层

目录 2.1 物理层的基本概念 2.2.1 数据通信系统的模型 2.2.2 有关信号的几个基本概念 1.通信 2.调制 3.编码 2.2.3 信道的极限容量 1.信道能够通过的频率范围&#xff08;奈氏准则&#xff09; 2. 信噪比&#xff08;香农公式&#xff09; 3.奈氏准则与香农公式的比…

Linux操作系统CentOS7安装mysql5.7.x

一、下载mysql5.7.x安装包 &#x1f308; MySQL官方下载&#xff1a;https://dev.mysql.com/downloads/mysql/5.7.html 注意&#xff0c;需要在Windows上解压之后&#xff0c;会有两个压缩包&#xff0c;将其中一个上传 二、将mysql5.7.x安装包上传到Linux服务器 使用 Xftp 上传…

NeurIPS 2022 Spotlight | SNAKE:首个同时进行隐式重建和三维特征点提取的方法

原文链接&#xff1a;https://www.techbeat.net/article-info?id4361 作者&#xff1a;钟程亮 3D特征点检测在物体识别、场景重建等任务中有着重要作用。然而由于点云数据采样的稀疏性&#xff0c;从中检测出3D特征点是一项很有挑战性的任务。虽然原始点云的获取方式有很多种&…

Kafka基础_1

Kafka系列 注&#xff1a;大家觉得博客好的话&#xff0c;别忘了点赞收藏呀&#xff0c;本人每周都会更新关于人工智能和大数据相关的内容&#xff0c;内容多为原创&#xff0c;Python Java Scala SQL 代码&#xff0c;CV NLP 推荐系统等&#xff0c;Spark Flink Kafka Hbase …

一文讲懂泛型

Java高级Java高级语言特性一. 泛型1. 1 为什么我们需要泛型1. 2 泛型类和泛型接口的定义1. 3 泛型方法1. 4 限定类型变量1. 5 泛型中的约束和局限性1. 6 泛型中的继承规则1. 7 通配符类型1.7.1 问题抛出&#xff0c;为啥需要通配符&#xff1f;1.7.2 &#xff1f; extends X1.7…

RocketMq的基本概念

&#x1f3b6; 文章简介&#xff1a;RocketMq的基本概念 &#x1f4a1; 创作目的&#xff1a;关于RocketMq的基本概念的大致介绍 ☀️ 今日天气&#xff1a;阳光明媚。 &#x1f4dd; 每日一言&#xff1a;冬有冬的来意&#xff0c;雪有雪的秘密。 文章目录&#x1f436; 1、Ro…

MySQL~DQL查询数据

4、DQL查询数据&#xff08;最重点&#xff09; 4.1、DQL &#xff08;Data Query LANGUAGE&#xff1a;数据查询语言&#xff09; 所有的查询操作都用它 Select简单的查询&#xff0c;复杂的查询它都能做~数据库中最核心的语言&#xff0c;最重要的语句使用频率最高 SELEC…

Kafka 集群部署与测试

安装Kafka&#xff08;需要JDK和Zookeeper&#xff09;: 下载Kafka安装包&#xff0c;并解压至node01节点中的/opt/apps目录下。修改配置文件。在server.properties配置文件中指定broker编号、Kafka运行日志存放的路径、指定Zookeeper地址和本地IP。添加环境变量。在/etc/prof…

[ vulhub漏洞复现篇 ] GhostScript 沙箱绕过(任意命令执行)漏洞CVE-2018-19475

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

【IDEA】# 快速生成logger、通过Maven的profile配置实现环境的快速切换、常用基础设置

1. 快速生成logger 打开 Settings&#xff0c;找到 Editor 目录下的 Live Templates 选中 Java&#xff0c;点击右侧的加号&#xff0c;创建一个新的模板 在创建模板的相关位置&#xff0c;填上对应的值 Abbreviation&#xff1a;触发的关键字&#xff08;此处我使用的是 l…

Postman进阶篇(十二)-在脚本中使用pm对象访问接口响应数据(pm.response.*)

在之前的文章中介绍过postman中的两个脚本——pre-request script或test script&#xff0c;在这两个脚本中都有使用到pm对象。&#xff08;pre-request script详细介绍、Test script详细介绍&#xff09;pm对象是在postman的脚本中非常重要&#xff0c;也是十分常用的方法。本…

SpringCloud学习笔记 - Nacos配置中心搭建 - Nacos Config

Nacos 提供用于存储配置和其他元数据的 key/value 存储&#xff0c;为分布式系统中的外部化配置提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config&#xff0c;您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。 Spring Cloud Alibaba Nac…

Volo - Rust gRPC 框架入门

一、参考资料 Volo-GitHub Volo-Overview 二、开发环境搭建 1、安装脚手架 # 安装 volo-cli cargo install volo-cli # 验证安装 volo help 2、编写 IDL # 文件 volo_demo.protosyntax "proto3"; package volo.demo;message Item {int64 id 1;string title …

React学习26(react-redux优化 工作使用)

项目结构 优化说明 1&#xff09;容器组件和UI组件混合成一个文件 2&#xff09;无需自己给容器传递store&#xff0c;在index.js入口文件给包裹一个Provider <Provider store {store}><App/> </Provider> 3&#xff09;使用了react-redux后也不用自己在…

Python入门教程:基本运算符

1.运算符 计算机可以进行的运算有很多种&#xff0c;可不只加减乘除这么简单&#xff0c;运算按种类可分为算数运算、比较运算、逻辑运算、赋值运算、成员运算、身份运算、位运算&#xff0c;今天我们暂只学习算数运算、比较运算、逻辑运算、赋值运算、成员运算 2.算数运算 …

数据聚合、数据同步

文章目录数据聚合Bucket聚合语法聚合结果排序限定聚合范围Metric聚合语法RestAPI实现聚合数据同步发送MQ消息接收MQ消息数据聚合 Bucket聚合语法 GET /hotel/_search {"size": 0, // 设置size为0&#xff0c;结果中 不包含文档&#xff0c;只包含聚合结果~"…