首页 > 其他分享 >树状数组(2)-- 逆序对计算

树状数组(2)-- 逆序对计算

时间:2023-11-10 23:34:09浏览次数:32  
标签:temp 树状 -- record int num 数组 逆序

题干引入

洛谷 P1908
LeedCode LCR 170

逆序数

(和线代中定义一致)在一个数字序列中,后面比前面小的数字个数之和
如 8 4 5 9 1 2 3 3 的逆序数为:6 +4 + 4+ 4+ 0+ 0+ 0 +0 = 18
使用一种办法求出逆序数

树状数组解法

根据上面序列中的数组出现次数,可以构建如下桶:

ID 1 2 3 4 5 6 7 8 9
num 1 1 2 1 1 0 0 1 1

我们根据上面的表构建树状数组
当我们从原列表的后面向前面遍历,储水式num都为0,对元素 \(a_{i}\),将其在表中的num+1,我们发现其逆序数就等于表前面小于 $a_i $ 元素的num之和。(因为是从后面遍历,如果比该元素小的且在后面的已经遍历过
因此:只需要每次加上 \(a_i\)前面之和即可

离散化

我们发现,如果序列为 1 2 100000000000000000000000 ... 就会造成构建树状数组的时候非常大,中间大量空间被浪费,因此我们先进行离散化

代码:

#include <algorithm>
#include <iostream>
using namespace std;
const int N = 5 * 10e5 + 10;
int t[N], record[N], temp[N];
int n;
void Madd(int x, int k) {
	for (; x <= n; x += x & -x) t[x] += k;
}
int Mask(int x) {
	int res = 0;
	for (; x; x -= x & -x) res += t[x];
	return res;
}
//离散化时使用sort函数用来比较的函数
bool cmp(int a, int b) {
	return a < b;
}
int main() {
	int _ = 1;
	while (_--) solve();
	return 0; 
}

solve()函数具体步骤:

void solve() {
//接受输入
	cin >> n;
	for (int i = 0; i < n; i++) cin >> record[i], temp[i] = record[i];
	//离散化
	sort(temp, temp + n, cmp);
	//lower_bound返回record[i]在temp数组中对应位置的迭代器,减去temp再加1即可获得record[i]在原数组中排序好之后的位置
	for (int i = 0; i < n; i++) record[i] = lower_bound(temp, temp + n, record[i]) - temp + 1;
	
	long long res = 0;
	for (int i = n; i > 0; i--) {
		Madd(record[i - 1], 1);
		res += Mask(record[i - 1] - 1);
	}
	cout << res << endl;
}

标签:temp,树状,--,record,int,num,数组,逆序
From: https://www.cnblogs.com/C-qian/p/17825338.html

相关文章

  • C++ insert into tables of pgsql via libpq-fe.h and compile by g++-13
    1.Installlibpq-devsudoaptinstalllibpq-devlocatelibpq-fe.h/usr/include/postgresql/libpq-fe.h 2.createtablet1createtablet1(idbigserialnotnullprimarykey,authorvarchar(40)notnull,commentvarchar(40)notnull,contentvarchar(40)notn......
  • FOC学习笔记-基于灯哥FOC
    1、foc控制技术现在无刷电机越来越多的进入人们的视野,因为他的控制精度更高,相对直流电机而言可以更稳定的工作等特点,被越来越多的应用于机器人行业,而无刷电机的控制离不开FOC控制。FOC(field-orientedcontrol)为磁场导向控制,又称为矢量控制(vectorcontrol),是一种利用变频器(VFD)控制......
  • 目录
    etc服务,配置文件dev存放硬件设备文件home存放用户自己的文件run运行目录sbin存放超级管理员命令tmp存放临时文件usr应用程序var存放日志MBR有64个字节,一个16个字,所以MBR最多分四个主分区,选一块主分区变成扩展分区,扩展分区里划罗辑分区......
  • Linux常用命令——tar文件的压缩与解压缩
    tar   选项   包名    文件名tar本身没有压缩功能,只有打包功能,但是tar可以调用压缩工具;以下是常用命令:-c  创建归档文件-v  显示过程-x  展开归档文件-f  操作归档文件-C  指定解压路径-z  调用gzip压缩工具-j  调用bzip2压缩工具-J......
  • 多级缓存
    传统缓存的问题传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,存在下面的问题:●请求要经过Tomcat处理,Tomcat的性能成为整个系统的瓶颈●Redis缓存失效时,会对数据库产生冲击多级缓存方案多级缓存就是充分利用请求处理的每个环节,分别添加缓存,减轻Tomcat......
  • 有什么可以自动保存微信文件的方法么?
    8-3本文要介绍的方法,可以自动帮你保存微信上收到的文件型数据,比如文件、图片、视频,如果你的工作需要每天或者经常保存大量的从微信收到的文件型数据,也许本文适合你,本文介绍的工具,对微信多开也有效果,并且可以单独对某些群聊或者对话里的文件型数据做自动保存。 以下正文 首先要准......
  • 基因注释软件SNAP的安装
     001、下载软件包:官网:http://korflab.ucdavis.edu/software.html 002、下载安装包、及安装wget-chttp://korflab.ucdavis.edu/Software/snap-2013-11-29.tar.gztar-xzfsnap-2013-11-29.tar.gzcdsnapmake 003、调用测试(base)[root@pc1snap]#./snap ......
  • java-流程控制
    第四章流程控制引入【1】流程控制的作用:流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。【2】控制语句的分类:控制语句分为三类:顺序、选择和循环。“顺序结构”代表“先执行a,再执行b”的逻辑。“条件判断结构”代表“如果......
  • 执行以下程序,输出结果为()
    执行以下程序,输出结果为()varone;vartwo=null;console.log(one==two,one===two);truefalse变量one只声明未赋值,所以其值为undefined,在使用“”对undefined和null进行比较时,不能将null和undefined转换成其他任何值,并且规定undefined==null返回结果为true,而使用“=......
  • 每日总结20231110
    代码时间(包括上课)5h代码量(行):100行博客数量(篇):1篇相关事项:1、今天是周五,天气很冷,还下雪来着,所以不愿意出被窝,所以上午下午赖床来着。2、今天晚上进行了C#的相关练习,对C#也有了一定的理解了。3、今天晚上打算复习复习数学,明天有考试,加油,加油,加油!......