逆序数的概念:对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时,就说有1个逆序。一个排列中所有逆序总数叫做这个排列的逆序数。

解决思路:

HDU-1394

1、线段树:通过保存区间内数的出现次数,每次插入一个数前把比它小(大)的区间内的总数累加。

 //求逆序数 线段树法
//原理,因为输入是依次输入的,所以每次输入一个数,只要查找比这个数小数的个数并累加就行了。
//顺序查找的复杂度是O(n),很容易想到用线段树保存每个数的出现次数,每次输入在比他小(大)的区间中查找总数就行了
#include <iostream>
#define N 5010
using namespace std;
int tree[N<<];//线段树保存了每个区间内数字出现总数
void CreatTree(int node,int l,int r)
{
if(l==r)
{
tree[node]=;
return ;
}
int mid=(l+r)>>;
CreatTree(node<<, l, mid);
CreatTree(node<<|, mid+, r);
tree[node]=tree[node<<]+tree[node<<|];
}
void Insert(int node,int num,int l,int r)
{
if(l==num&&r==l)
{
tree[node]++;
return ;
}
int mid=(l+r)>>;
if(num<=mid)
Insert(node<<, num, l, mid);
else
Insert(node<<|, num, mid+, r);
tree[node]=tree[node<<]+tree[node<<|];
}
int Query(int node,int ql,int qr,int l,int r)
{
if(qr<ql)
return ;
if(ql<=l&&r<=qr)
return tree[node];
int mid=(l+r)>>;
int rec=;
if(ql<=mid)
rec+=Query(node<<, ql, qr, l, mid);
if(qr>mid)
rec+=Query(node<<|, ql, qr, mid+, r);
return rec;
}
int main(int argc, const char * argv[]) {
int n;
while(cin>>n)
{
int ans=,temp;
int num[N];
CreatTree(, , n-);
for(int i=;i<n;i++)
{
cin>>temp;
num[i]=temp;
Insert(, temp, , n-);
ans+=Query(, temp+,n-, , n-);
}
int sum=ans;
for(int i=;i<n;i++)
{
ans=ans-num[i]+n-num[i]-;
if(ans<sum)
sum=ans;
}
cout<<sum<<endl;
}
return ;
}

2、归并排序:归并排序过程中,如果左序列的第j个值大于有序列第k个值,那么j~lenl的值都大于k,所以每次ans+=

id-(left+j)+1。完成整个归并排序,就可以统计所有逆序数对的数量。

 //求逆序数 归并排序法
//在归并排序过程中,每次对左右两个有序数列排序时,如果左边序列的第j个值大于右边序列k个值
//那么说明左边序列的j~lenl个值都大于第k个值,所以把其加到ans中
#include <iostream>
#define N 5010
using namespace std;
bool cmp(int a,int b)
{
return a<=b;
}
int ans;
void MergeArr(int num[], int left, int mid, int right)
{
int AL[N], AR[N],lenl=mid-left+,lenr=right-mid;
for (int i = ;i < lenl;i++)
AL[i] = num[left + i];
for (int i = ;i < lenr;i++)
AR[i] = num[mid + + i];
int j = , k = ,pos=left;
while (j < lenl&&k < lenr)
{
if (cmp(AL[j], AR[k]))
num[pos++] = AL[j++];
else
num[pos++] = AR[k++],ans+=mid-(left+j)+;//关键步骤
}
while (j < lenl)
num[pos++] = AL[j++];
while (k < lenr)
num[pos++] = AR[k++];
}
void MergeSort(int num[], int left, int right)
{
if (left < right)
{
int mid = (right + left) / ;
MergeSort(num, left, mid);
MergeSort(num, mid+, right);
MergeArr(num, left, mid, right);
}
}
int main() {
int n;
while(cin>>n)
{
ans=;
int num[N],temp[N];
for(int i=;i<n;i++)
cin>>num[i],temp[i]=num[i];
MergeSort(temp, , n-);
int sum=ans;
for(int i=;i<n;i++)
{
ans=ans-num[i]+n-num[i]-;
if(ans<sum)
sum=ans;
}
cout<<sum<<endl;
}
return ;
}

求逆序数的方法--线段树法&归并排序法的更多相关文章

  1. HDU 1394.Minimum Inversion Number-最小逆序数-完全版线段树(单点增减、区间求和)

    HDU1394.Minimum Inversion Number 这个题求最小逆序数,先建一个空的树,然后每输入一个值,就先查询一下,查询之后,更新线段树,然后遍历一遍,每次将第一个数放到最后之后,减 ...

  2. codevs1688 求逆序对(权值线段树)

    1688 求逆序对  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 给定一个序列a1,a2,…, ...

  3. hdu 1394 Minimum Inversion Number(线段树之 单点更新求逆序数)

    Minimum Inversion Number                                                                           T ...

  4. Ultra-QuickSort (求逆序数+离散化处理)、Cows、Stars【树状数组】

    一.Ultra-QuickSort(树状数组求逆序数) 题目链接(点击) Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total ...

  5. poj 3067 Japan(树状数组求逆序数)

    链接:http://poj.org/problem?id=3067 题意:左边有n个城市,右边有m个城市,建k条道路,问有这k条道路中有多少个交点. 分析:将城市按x和y从小到大排序,对于每条道路,求 ...

  6. hiho一下 第三十九周 归并排序求逆序数

    题目链接:http://hihocoder.com/contest/hiho39/problem/1 ,归并排序求逆序数. 其实这道题也是可以用树状数组来做的,不过数据都比较大,所以要离散化预处理一下 ...

  7. poj 2299 Ultra-QuickSort :归并排序求逆序数

    点击打开链接 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 34676   Accepted ...

  8. 线段树求逆序数方法 HDU1394&amp;&amp;POJ2299

    为什么线段树能够求逆序数? 给一个简单的序列 9 5 3 他的逆序数是3 首先要求一个逆序数有两种方式:能够从头開始往后找比当前元素小的值,也能够从后往前找比当前元素大的值,有几个逆序数就是几. 线段 ...

  9. HDU 1394 Minimum Inversion Number (线段树 单点更新 求逆序数)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给你一个n个数的序列,当中组成的数仅仅有0-n,我们能够进行这么一种操作:把第一个数移到最 ...

随机推荐

  1. linux常用命令:ifconfig 命令

    许多windows非常熟悉ipconfig命令行工具,它被用来获取网络接口配置信息并对此进行修改.Linux系统拥有一个类似的工具,也就是ifconfig(interfaces config).通常需 ...

  2. sql的函数和存储过程的区别

    本文部分内容转自http://www.cnblogs.com/lengbingshy/archive/2010/02/25/1673476.html 本质上没区别.只是函数有如:只能返回一个变量的限制 ...

  3. MySQL Crash Course #11# Chapter 20. Updating and Deleting Data

    INDEX Updating Data The IGNORE Keyword Deleting Data Faster Deletes Guidelines for Updating and Dele ...

  4. velocity #parse抽象重用部分组件

    在某些时候,处于重用的目的,我们会选择将可以重用的部分内容剥离在单独的模板文件中,比如对于查询页面的表格部分,因为现在很多的条件可能是通过弹出查询框的方式来实现,而作为普通页面的时候,他们会有更多的功 ...

  5. troubleshooting-windows 在 CDH集群环境读取 Hive 表 KrbException: Cannot locate default realm

    KrbException: Cannot locate default realm 解决办法 1)拷贝需要组件的配置文件到项目中的 /resources/目录.如hadoop,目录/etc/hadoo ...

  6. zabbix zabbix_agentd.conf详解

    # This is a config file for the Zabbix agent daemon (Unix) # To get more information about Zabbix, v ...

  7. SCP报错:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

    经过google,出现这个问题的原因是,这是ssh的问题, GkFool大神说(第一次使用SSH连接时,会生成一个认证,储存在客户端的known_hosts中) 我的解决办法是: ssh-keygen ...

  8. .Family_物联网

    群名称 : .Family_物联网 QQ群号: 群介绍 基于嵌入式,构建各通信模式,网关,平台软件,工业系统等领域,欢迎各位朋友加群,交流学习!

  9. codevs & vijos 爱在心中 - Tarjan

    描述 “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有 ...

  10. 32位MD5加密补齐丢失的0

    /// <summary> /// 获取32位MD5加密字符串(已补完0) /// </summary> /// <param name="strWord&qu ...