树状数组 求解 逆序数对

【前言】

 

好吧,我承认这个是完全抄袭过来的。而且我还没付诸实践的。

 

之前写过一个归并排序求解逆序数对的:http://blog.csdn.net/Human_CK/archive/2011/03/11/6239453.aspx

 

不过我看了http://blog.foreverzeus.com/?p=853之后觉得用树状数组其实可能更简单更容易理解或许还会更快。

 

【思路】

 

假设有1到n的数任意排列,要求其逆序数对。

 

5 2 1 3 4

 

首先初始化树状数组为0。

 

把5放进去,把5进行加1操作。并计算sum[5]。此时数组为0 0 0 0 1。

 

对于第i个数,包括其本身最多会产生i个逆序数对。由于此时数组保存的是之前所有的数,我们可以计算出此时比当前数小的数的个数,在这里这个个数为1(包括5本身),说明在这之前有1个数比它小(即不能构成逆序数对),再用i-sum[5](此时i=1,sum[5]=1)=0得到此时逆序数对为0。

 

对于第二个数,加1并计算得到0 1 0 0 1。

 

sum[2] = 1,i-sum[2](此时i=2,sum[2]=1)=1,说明此时有1个逆序数(5是2的逆序数)。

 

当i=3时,得到1 1 0 0 1,i-sum[1](i=3,sum[1]=1)=2,说明有两个逆序数。

 

以此类推。

 

我觉得这个思路还是很简单的,代码写起来也很容易,因为树状数组本身的代码就很简单。

 

而对于不连续的数字,可以先将其离散化。

 

比如将 9 1 0 5 4 离散为 5 2 1 3 4。即每个数对应为其在这个数列中的排名。

 

【代码】

 

ans[]用于记录离散后的数值。

add()用于更新节点。

calsum()为计算树状数组到某个点的总和。

cnt用于记录总逆序数对个数。

 

  

 

【P.S】

 

其实我是在找怎样用树状数组“更新区域查询节点”的……

 

谁知道找了零零散散的一些,没有完整的比较好理解的思路……

 

然后就在无意中看到了这个,也算是一个收获吧!

 

继续征程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值