博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
算法学习(二)——树状数组求逆序数
阅读量:5356 次
发布时间:2019-06-15

本文共 1961 字,大约阅读时间需要 6 分钟。

1、什么是逆序数?2、用树状数组求逆序数的总数         2.1该背景下树状数组的含义         2.2如何使用树状数组求逆序数总数         2.3 C++实现代码
目录

 

1、什么是逆序数?

         在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序数的总数就是这个排列的逆序数。

 

2、用树状数组求逆序数的总数

         2.1该背景下树状数组的含义

         我们假设一个数组A[n],当A[n]=0时表示数字n在序列中没有出现过,A[n]=1表示数字n在序列中出现过。A对应的树状数组为c[n],则c[n]对应维护的是数组A[n]的内容,即树状数组c可用于求A中某个区间的值的和。

         树状数组的插入函数(假设为 void insert(int i,int x) )的含义:在求逆序数这个问题中,我们的插入函数通常使用为insert( i , 1 ),即将数组A[i]的值加1 (A数组开始应该初始化为0,所以也可以理解为设置A[ i ]的值为1,即将数字i 加入到序列的意思 )。,同时维护c数组的值。

         树状数组中区间求和函数(假设函数定义为: int getsun(int i ) )的含义:该函数的作用是用于求序列中小于等于数字 i 的元素的个数。这个是显而易见的,因为树状数组c 维护的是数组A的值,则该求和函数即是用于求下标小于等于 i 的数组A的和,而数组A中元素的值要么是0要么是1,所以最后求出来的就是小于等于i的元素的个数。

         所以要求序列中比元素a大的数的个数,可以用i - getsum(a)即可( i 表示此时序列中元素的个数)。

 

         2.2如何使用树状数组求逆序数总数

         首先来看如何减小问题的规模:

         要想求一个序列 a b c d,的逆序数的个数,可以理解为先求出a b c的逆序数的个数k1,再在这个序列后面增加一个数d,求d之前的那个序列中值小于d的元素的个数k2,则k1+k2即为序列a b c d的逆序数的个数。

         举个例子加以说明:

  假设给定的序列为 4 3 2 1,我们从左往右依次将给定的序列输入,每次输入一个数temp时,就将当前序列中大于temp的元素的个数计算出来,并累加到ans中,最后ans就是这个序列的逆序数个数。

 

序列的变化(下划线为新增加元素)

序列中大于新增加的数字的个数

操作

{ }

0

初始化时序列中一个数都没有

{

4 }

0

往序列中增加4,统计此时序列中大于4的元素个数

{4 3 }

1

往序列中增加3,统计此时序列中大于3的元素个数

{4 3 2}

2

往序列中增加2,统计此时序列中大于2的元素个数

{4 3 2 1}

3

往序列中增加1,统计此时序列中大于1的元素个数

         当所有的元素都插入到序列后,即可得到序列{4 3 2 1}的逆序数的个数为1+2+3=6.

        

         2.3 C++实现代码如下:

 

#include 
#include
using namespace std;#define N 1010int c[N]; int n;int lowbit(int i){ return i&(-i);}int insert(int i,int x){ while(i<=n){ c[i]+=x; i+=lowbit(i); } return 0;}int getsum(int i){ int sum=0; while(i>0){ sum+=c[i]; i-=lowbit(i); } return sum;}void output(){ for(int i=1;i<=n;i++) cout<
<<" "; cout<
>n){ int ans=0; memset(c,0,sizeof(c)); for(int i=1;i<=n;i++){ int a; cin>>a; insert(a,1); ans+=i-insert(a);//统计当前序列中大于a的元素的个数 } cout<
<

 

转载于:https://www.cnblogs.com/xiongmao-cpp/p/5043340.html

你可能感兴趣的文章
C# Fade Form Effect With the AnimateWindow API Function
查看>>
golang多维数组的切片
查看>>
IP 网际协议
查看>>
C语言_第五章__实践(密码转换)
查看>>
docker 容器后台运行命令
查看>>
jquery 获取css position的值
查看>>
面向对象的程序设计
查看>>
a标签添加点击事件
查看>>
Context.startActivity出现AndroidRuntimeException
查看>>
Intellij idea创建javaWeb以及Servlet简单实现
查看>>
代理网站
查看>>
Open multiple excel files in WebBrowser, only the last one gets activated
查看>>
FFmpeg进行视频帧提取&音频重采样-Process.waitFor()引发的阻塞超时
查看>>
最近邻与K近邻算法思想
查看>>
【VS开发】ATL辅助COM组件开发
查看>>
FlatBuffers In Android
查看>>
《演说之禅》I &amp; II 读书笔记
查看>>
thinkphp3.2接入支付宝支付接口(PC端)
查看>>
response和request
查看>>
【转】在Eclipse中安装和使用TFS插件
查看>>