HDU 1394 Minimum Inversion Number (树状数组)
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 (树状数组)的更多相关文章
- HDU 1394 Minimum Inversion Number ( 树状数组求逆序数 )
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number ...
- HDU 1394 Minimum Inversion Number (树状数组求逆序对)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题目让你求一个数组,这个数组可以不断把最前面的元素移到最后,让你求其中某个数组中的逆序对最小是多 ...
- hdu 1394 Minimum Inversion Number - 树状数组
The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that ...
- HDU 1394 Minimum Inversion Number (树状数组 && 规律 && 逆序数)
题意 : 有一个n个数的数列且元素都是0~n-1,问你将数列的其中某一个数及其前面的数全部置到后面这种操作中(比如3 2 1 0中选择第二个数倒置就产生1 0 3 2)能产生的最少的逆序数对是多少? ...
- [hdu1394]Minimum Inversion Number(树状数组)
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)
HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意: 给一个序列由 ...
- HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)
HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...
- HDU 1394 Minimum Inversion Number(线段树/树状数组求逆序数)
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- hdu 1394 Minimum Inversion Number(逆序数对) : 树状数组 O(nlogn)
http://acm.hdu.edu.cn/showproblem.php?pid=1394 //hdu 题目 Problem Description The inversion number ...
- HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)
题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS Memory Limit: 32768 K Description The inve ...
随机推荐
- 【第二周】Java实现英语文章词频统计(改进1)
本周根据杨老师的spec对英语文章词频统计进行了改进 1.需求分析: 对英文文章中的英文单词进行词频统计并按照有大到小的顺序输出, 2.算法思想: (1)构建一个类用于存放英文单词及其出现的次数 cl ...
- .net MVC中使用angularJs刷新页面数据列表
使用angularjs的双向绑定功能,定时刷新页面上数据列表(不是刷新网页,通过ajax请求只刷新数据列表部分页面),实例如下: @{ Layout = null; } <!DOCTYPE ht ...
- 【bzoj3576】[Hnoi2014]江南乐 博弈论+SG定理+数学
题目描述 两人进行 $T$ 轮游戏,给定参数 $F$ ,每轮给出 $N$ 堆石子,先手和后手轮流选择石子数大于等于 $F$ 的一堆,将其分成任意(大于1)堆,使得这些堆中石子数最多的和最少的相差不超过 ...
- java中枚举型的定义以及使用
1.如何定义枚举型 public enum gender{ GEN1("男","1"), GEN2("女","0"); ...
- 高rong效chang的可持久化treap
很多人觉得可持久化treap很慢,但是事实上只是他们可持久化treap的写法不对.他们一般是用split和merge实现所有功能,但是这样会有许多不必要的分裂.其实我们可以用一种特殊的方式来实现插入和 ...
- 转:pairwise 代码参考
Learning to rank with scikit-learn: the pairwise transform http://fa.bianp.net/blog/2012/learning-to ...
- java学习5-jar包的下载以及导入
1.出现未导入包的情况 ,表示当前jdk不 2.百度下载jar包 3.File. 未完待续http://blog.csdn.net/a153375250/article/details/5085104 ...
- [AT2064] [agc005_f] Many Easy Problems
题目链接 AtCoder:https://agc005.contest.atcoder.jp/tasks/agc005_f 洛谷:https://www.luogu.org/problemnew/sh ...
- [HNOI2014]江南乐 博弈论
题面 题面 题解 首先我们知道一个关于除法的重要性质:对于一个固定的\(i\),表达式\(\frac{i}{m}\)的取值只有根号个. 因此我们考虑如何优化SG函数的求解. 观察到在取值相同的同一段中 ...
- [SDOI2011]黑白棋 kth - nim游戏
题面 题面 题解 观察题目,我们可以发现,这个游戏其实就是不断再把对方挤到一边去,也就是黑子不断往左走,白子不断往右走. 因此可以发现,如果将黑白子按顺序两两配对,那么它们中间的距离会不断缩小,且每次 ...