对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的。

一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2)。

那么我们通过树状数组可以明显提高时间效率。

我们可以按照排列的顺序依次将数字放入树状数组中,并依次更新预与之相关联的树状数组元素。那么在将其更新完毕后,我们知道每个数对应的树状数组元素的左边的数肯定比它小,我们在以序列顺序依次更新树状数组时,如果有值在它前面出现,那么它对应的树状数组元素(在这个题目里存放的是个数)值必然增加,我们可以利用树状数组快速求一段区间的总和(这一段是比它小的数字的总个数)。那么用i-sum得到的就是逆序数了。

当然,另外还要注意到一点由于数字可能很大,那么我们开那么大的数组是不合理地,为此我们用离散化的方式来处理r[num[i].tag]=i;r[MAXN]存放离散数据,即用i=1;i<=t;i++从小到大表示递增的数据,以便充分使用每一个数组元素,类似于map的功能,映射。)

所以因为有这一步,所以要先sort,然后将数值离散化。这样每一个数的更新仅需o(log(n))

总的时间降为o(nlog(n))。

带着代码再加深理解:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 5005
using namespace std;
struct node
{
int val;
int tag;
}num[MAXN];
int t;
int r[MAXN],c[MAXN];//c[MAXN]为已经离散化的树状数组元素
bool cmp(node a,node b)
{
return a.val<b.val;
}
int lowbit(int x)
{
return x&(-x);
}
void update(int x)
{
while(x<=t)
{
c[x]+=;
x+=lowbit(x);
}
}
int s(int x)
{
int sum=;
while(x>)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
int i,j,ans,min;
while(cin>>t)
{
ans=;
memset(c,,sizeof(c));
for(i=;i<=t;i++)
{
scanf("%d",&num[i].val);
num[i].tag=i;
}
sort(num+,num+t+,cmp);
for(i=;i<=t;i++)
{
r[num[i].tag]=i;//进行离散化
}
for(i=;i<=t;i++)
{
update(r[i]);
ans=ans+i-s(r[i]);
}
min=ans;
for(i=;i<t;i++)
{
ans=ans-r[i]++t-r[i];
min=ans<min?ans:min;
}
printf("%d\n",min);
}
return ;
}

HDU 1394 树状数组+离散化求逆序数的更多相关文章

  1. POJ 2299 Ultra-QuickSort (树状数组+离散化 求逆序数)

    In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a seque ...

  2. CF 61E 树状数组+离散化 求逆序数加强版 三个数逆序

    http://codeforces.com/problemset/problem/61/E 题意是求 i<j<k && a[i]>a[j]>a[k] 的对数 会 ...

  3. POJ 2299 树状数组+离散化求逆序对

    给出一个序列 相邻的两个数可以进行交换 问最少交换多少次可以让他变成递增序列 每个数都是独一无二的 其实就是问冒泡往后 最多多少次 但是按普通冒泡记录次数一定会超时 冒泡记录次数的本质是每个数的逆序数 ...

  4. 树状数组||归并排序求逆序对+离散化 nlogn

    我好咸鱼. 归并排序之前写过,树状数组就是维护从后往前插入,找比现在插入的数大的数的数量. 如果值域大,可以离散化 #include <cstdio> #include <cstri ...

  5. hdu 5792 树状数组+离散化+思维

    题目大意: Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a< ...

  6. POJ 3067 - Japan - [归并排序/树状数组(BIT)求逆序对]

    Time Limit: 1000MS Memory Limit: 65536K Description Japan plans to welcome the ACM ICPC World Finals ...

  7. HDU 1394 树状数组求逆序对

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  8. [hdu 4417]树状数组+离散化+离线处理

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 把数字离散化,一个查询拆成两个查询,每次查询一个前缀的和.主要问题是这个数组是静态的,如果带修改 ...

  9. Disharmony Trees HDU - 3015 树状数组+离散化

    #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using ...

随机推荐

  1. 深入解析Ajax——系列(一)

    常常写脚本的人.有时候会用到$ajax,有时候也会用到$post和$get,这几个方法都是用来从Webserver上获取静态的数据文件. jQuery对ajax操作进行了封装,在jquery中$.aj ...

  2. Oracle-31-对视图DML操作

    一.对视图进行DML操作 1.创建一个视图v_person create or replace noforceview v_person as select *from person where id ...

  3. MySQL:unknown variable &#39;master-host=masterIP&#39; [ERROR] Aborting

    <span style="font-size:18px;">120401 15:45:44 [ERROR] C:\Program Files\MySQL\MySQL S ...

  4. HTML+CSS要点

    1.td占据多行 / 列时,其挤开的 td 不写(但是包裹 td 的 tr 要写) 2. display:td 的元素中的文本默认垂直不居中(table中的td中的文本是垂直居中的) 3.th虽然定义 ...

  5. Linux Setuid(SUID)和Setgid(SGID) sticky bit

    http://www.php100.com/html/webkaifa/Linux/2010/0812/6392.html 1.setuid和setgid的解说 setuid和setgid位是让普通用 ...

  6. Django-中介模型

    有多对多字段的时候自己创建的第三章表就是中介模型 class Article(models.Model): ''' 文章表 ''' title = models.CharField(max_lengt ...

  7. Django-models-m2m

    在Django的orm中,如果有多对多的字段,那么他的第三张表时自己生成的,参考官方文档发现第三张表可以自己写↓: 而且第三张表好像是可以自定制的 from django.db import mode ...

  8. 高性能MySQL(二)

    MySQL基准测试 为什么需要benchmark 验证基于系统的假设,确认是否符合实际情况 重现系统中的某些异常行为,以解决它们 测试系统当前的运行情况,如果不清楚当前性能,就无法确认优化效果 模拟比 ...

  9. python staticmethod和classmethod(转载)

    staticmethod, classmethod 分别被称为静态方法和类方法. staticmethod 基本上和一个全局函数差不多,只不过可以通过类或类的实例对象(python里只说对象总是容易产 ...

  10. 初步探讨WPF的ListView控件(涉及模板、查找子控件) - GavinJun

    本文结合模板的应用初步介绍ListView的应用 一.Xaml中如何建立数据资源 大部分数据都会来自于后台代码,如何Xaml同样的建立数据源呢?比如建立一个学生List: 首先引入命名空间: xmln ...