题目链接

Problem Description

The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.

For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:

a1, a2, ..., an-1, an (where m = 0 - the initial seqence)

a2, a3, ..., an, a1 (where m = 1)

a3, a4, ..., an, a1, a2 (where m = 2)

...

an, a1, a2, ..., an-1 (where m = n-1)

You are asked to write a program to find the minimum inversion number out of the above sequences.

Input

The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.

Output

For each case, output the minimum inversion number on a single line.

Sample Input

10
1 3 6 9 0 8 5 7 4 2

Sample Output

16

题意

给你n个数字 这些数字都是从0到n-1的,每次把第一个位置的数字移到最后一位形成一个新的序列,然后求出这些序列的逆序数,最后输出最小的逆序数。

分析

什么是逆序数:对于数x和y,若y的位置在x的前面并且y比x大,那么(x,y)就是一个逆序数对,

普通方法解决:例子:

5  4  3  6  1  2
当输入5时,就用一个标记数组a[5]=1,(a数组初始化全部为零),然后从6开始往后遍历,当遇到a[i]==1时,说明i这个数在6之前出现过,那么6的逆序数对就增加一个。
输入4时同理。。。。

这种方法很容易想到,代码也很容易实现。两个for循环就行了,但是套路那么深,这道题怎么可能怎么简单,肯定会超时的,就得用树状数组来做了。

设e[ ]就是这个树状数组,e数组是用来维护a数组的信息,e[i]代表是在当前情况下从1到i这个区间已经出现的数的个数,如 e[3]=2 代表的是在 [1,3]已经出现了两个数字 e[n]=k,代表的是在[1,n]已经出现的数的个数, e[n]-e[3]所代表的意思就很显然是此时大于3的已经出现的数的个数,这不就是3的逆序数嘛~~~我等凡夫俗子老半天才看懂大神的代码

由于这道题的数据时从0到n-1的,当求出一个序列的逆序数后,把这个序列的第一个数放到最后的位置形成的新的序列,这个新的序列的逆序数和原来的逆序数是由一定的关系的:

假设num[]数组如下  个数n=6
1 4 3 5 0 2 这个序列的逆序数为 x
4 3 5 0 2 1 当把1放到后面时,0的逆序数就减少了一个 但是比1 大的2 3 4 5 就成了1的逆序数
3 5 0 2 1 4 当把4放到后面时,3,2,1,0的逆序数就各减少了一个 但是比4 大的5 就成了4的逆序数
所以可推出如下规律: 新的逆序数t=x-num[1] + n-1-num[i]
x-num[1]: 把第一个数字放到后面,比num[1]小的数字的逆序数减少了,
+ n-1-num[i]:把第一个数字放到后面,比num[1]大的数字就构成num[1]的逆序数

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; const int N=5010; int n,arr[N],num[N]; int lowbit(int x)
{
return x&(-x);
} void update(int id,int x)
{
while (id<=N)
{
arr[id]+=x;
id+=lowbit(id);
}
} int Sum(int id)
{
int ans=0;
while (id>0)
{
ans+=arr[id];
id-=lowbit(id);
}
return ans;
}
int main()
{
//freopen("1.txt","r",stdin);
while (scanf("%d",&n)!=EOF)
{
memset(arr,0,sizeof(arr));
int i,ans=0;
for (i=1; i<=n; i++)
{
scanf("%d",&num[i]);
ans+=Sum(n+1)-Sum(num[i]+1);//当前的逆序数个数
update(num[i]+1,1);
}
int tmp=ans;
for (i=1; i<=n; i++)
{
tmp+=n-1-num[i]-num[i];
ans=min(ans,tmp);
}
printf("%d\n",ans); }
return 0;
}

HDU 1394 Minimum Inversion Number (树状数组)的更多相关文章

  1. HDU 1394 Minimum Inversion Number ( 树状数组求逆序数 )

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number                         ...

  2. HDU 1394 Minimum Inversion Number (树状数组求逆序对)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题目让你求一个数组,这个数组可以不断把最前面的元素移到最后,让你求其中某个数组中的逆序对最小是多 ...

  3. hdu 1394 Minimum Inversion Number - 树状数组

    The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that ...

  4. HDU 1394 Minimum Inversion Number (树状数组 && 规律 && 逆序数)

    题意 : 有一个n个数的数列且元素都是0~n-1,问你将数列的其中某一个数及其前面的数全部置到后面这种操作中(比如3 2 1 0中选择第二个数倒置就产生1 0 3 2)能产生的最少的逆序数对是多少? ...

  5. [hdu1394]Minimum Inversion Number(树状数组)

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

  6. HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)

    HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意:  给一个序列由 ...

  7. HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)

    HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...

  8. HDU 1394 Minimum Inversion Number(线段树/树状数组求逆序数)

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

  9. hdu 1394 Minimum Inversion Number(逆序数对) : 树状数组 O(nlogn)

    http://acm.hdu.edu.cn/showproblem.php?pid=1394  //hdu 题目   Problem Description The inversion number ...

  10. HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)

    题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS     Memory Limit: 32768 K Description The inve ...

随机推荐

  1. IDEA中Git的更新/提交/还原方法

    记录一下在IDEA上怎样将写的代码提交到GitHub远程库: 下面这个图是基本的提交代码的顺序: 1. 将代码Add到stage暂存区本地修改了代码后,需先将代码add到暂存区,最后才能真正提价到gi ...

  2. pip使用国内镜像源

    windows版 1.在windows文件管理器中,输入 %APPDATA% 2.在该目录下新建pip文件夹,然后到pip文件夹里面去新建个pip.ini文件 3.在新建的pip.ini文件中输入以下 ...

  3. 【C++】深度探索C++对象模型读书笔记--执行期语意学(Runtime Semantics)

    对象的构造和析构: 全局对象 C++程序中所有的global objects都被放置在程序的data segment中.如果显式指定给它一个值,此object将以此值为初值.否则object所配置到的 ...

  4. linux 上传下载

    xshell yum就是傻瓜式的安装软件,你要装什么,yum什么就行了,红帽系统才有yum,乌班图和debian是没有的 输入命令:sudo yum -y install lrzsz rz  上传 从 ...

  5. 第112天:javascript中函数预解析和执行阶段

    关于javascript中的函数:  1.预解析:把所有的函数定义提前,所有的变量声明提前,变量的赋值不提前  2.执行 :从上到下执行,但有例外(setTimeout,setInterval,aja ...

  6. 【Python】内置函数

    一.内置函数表格 详细信息 二.内置函数详情 2.1 abs(x) 返回绝对值 1 2 >>> abs(-5) 5 2.2 all(iterable) 如果这个可迭代的元素都为真,就 ...

  7. Appium与Robotium区别

    Appium是基于UIAutomator框架实现的.Appium测试进程与目标应用进程是分开的,所以Appium不能直接访问目标应用的各种element属性进行copy&paste,而只能模拟 ...

  8. [四]SpringBoot 之 捕捉全局异常

    在class注解上@ControllerAdvice, 在方法上注解上@ExceptionHandler(value = Exception.class),具体代码如下: package me.shi ...

  9. vdbench测试过程中遇到的小问题

    1.报Slave hd2-0 prematurely terminated 错误 首先根据提示查看hd2-0.stdout.html文件获取更多的错误信息,这个问题一般是未安装vdbench或者路径不 ...

  10. 基于ORM实现用户登录

    1. 与数据库中的数据进行比较,检验用户名和密码是否正确. 2. 拿到的是QuerySet类型,类似于一个列表.验证成功/失败,返回到不同的页面. u = request.POST.get('user ...