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 ...
随机推荐
- Cmder命令行工具在Windows系统中的配置
一.Cmder简介 Cmder:一款用于Windows系统中,可增强传统cmd命令行工具的控制台模拟器(类似于Linux系统中的终端控制窗口) 特点: 无需安装,解压即用 可使用较多Linux命令,如 ...
- matlab 图像Mat类型矩阵中的值(uint8)类型转换,防止溢出
a=[50,60,70; 80,90,50; 100,55,40] 假设a是一个灰度图的mat形式(当然实际的size肯定比这大,我只是举例子),如果需要对这个矩阵的像素进行加减处理,很可能会产生溢出 ...
- egret 开发总结
用egret快两年了,开发过两款成功的游戏.<<妖怪修走 |诸神的黄昏>><<损友圈|我的地盘>> 妖怪修走是个重度游戏,付费率超高.也比较成功. 损友 ...
- Kafka在大型应用中的 20 项最佳实践
原标题:Kafka如何做到1秒处理1500万条消息? Apache Kafka 是一款流行的分布式数据流平台,它已经广泛地被诸如 New Relic(数据智能平台).Uber.Square(移动支付公 ...
- echarts tooltip 自定义formatter怎么设置颜色?
formatter: function(params) { var result = ''; params.forEach(function (item) { result += item.marke ...
- hive表信息查询:查看表结构、表操作等--转
原文地址:http://www.aboutyun.com/forum.PHP?mod=viewthread&tid=8590&highlight=Hive 问题导读:1.如何查看hiv ...
- BZOJ 1562 变换序列(二分图匹配)
显然每个位置只有两个情况,所以用二分图最大匹配来求解. 如果二分图有完全匹配,则有解. 关键是如何求最小的字典序解. 实际上用匈牙利算法从后面开始找增广路,并优先匹配字典序小的即可. # includ ...
- 【poj2409】Let it Bead Polya定理
题目描述 用 $c$ 种颜色去染 $r$ 个点的环,如果两个环在旋转或翻转后是相同的,则称这两个环是同构的.求不同构的环的个数. $r·c\le 32$ . 题解 Polya定理 Burnside引理 ...
- Linux实用命令行
对于Linux命令,我在学习和使用过程中是有一个循序渐进的过程的.适合小白学习快速使用.大笑 跳转目录:cd +路径 例如:cd /home/workspace 查看某个文件,常用的是查看日志:tai ...
- 【BZOJ4651】【NOI2016】网格(Tarjan,哈希)
[BZOJ4651][NOI2016]网格(Tarjan,哈希) 题面 BZOJ 洛谷 题解 首先把题目稍微变得好说一些,给定一个网格,已经删去了若干个格子 问最少删去多少个格子使得图不连通. 这题的 ...