Minimum Inversion Number  

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的整数,允许你每次将序列的头调到序列尾,让你求出最小的逆序和,
思路:先用线段树or树状数组预处理出原先的逆序和,然后再一个一个推出,每次操作后所产生的的新的逆序和,就拿样例来说,一开始的逆序和是22,如果将1调到末尾那里的话,原先在1后面比1小的数有1个,这个数是0,而当1调到后面的时候,在1前面的比一大的数有8个,为3,6,9,8,5,7,4,2,那么新序列的逆序和为22 - 1 + 8 = 29。以此类推
 
AC代码:线段树的方法,借鉴了notonlysuccess大神的姿势:
Memory: 320 KB   Time: 78 MS
#include <cstdio>
#include <iostream>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = ;
int sum[maxn<<];
void PushUp(int rt){
sum[rt] = sum[rt<<] + sum[rt<<|];
}
void build(int l,int r,int rt){
sum[rt] = ;
if(l == r) return ;
int m = (l + r) >> ;
build(lson);
build(rson);
return ;
}
void update(int p,int l,int r,int rt){
if(l == r){
sum[rt]++;
return ;
}
int m = (l + r)>>;
if(p <= m) update(p,lson);
else update(p,rson);
PushUp(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L <= l&&r <= R){
return sum[rt];
}
int m = (l + r)>>;
int ret = ;
if(L <= m) ret += query(L,R,lson);
if(R > m) ret += query(L,R,rson);
return ret;
}
int x[maxn];
int main(){
int n;
while(~scanf("%d",&n)){
build(,n - ,);
int sum = ;
for(int i = ;i < n;i++){
scanf("%d",&x[i]);
sum += query(x[i],n - ,,n - ,);
update(x[i],,n - ,);
}
int res = sum;
for(int i = ;i < n;i++){
sum += n - x[i] - x[i] - ;
res = min(res,sum);
}
printf("%d\n",res);
}
return ;
}

后来我有用树状数组做了一下,发觉树状数组一般都要比线段树要快~

Memory: 332 KB   Time: 31 MS
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = ;
int c[maxn];
int a[maxn];
int n;
inline int lowbit(int x){
return x&(-x);
}
int sum(int x){
int ret = ;
while(x > ){
ret += c[x];x -= lowbit(x);
}
return ret;
}
void add(int x,int d){
while(x <= n){
c[x] += d;x += lowbit(x);
}
}
int main(){
while(~scanf("%d",&n)){
memset(c,,sizeof(c));
memset(a,,sizeof(a));
int ans = ;
for(int i = ;i <= n;i++){
scanf("%d",&a[i]);
ans += i - - sum(a[i]);
add(a[i] + ,);
}
//cout<<ans<<endl;
int MIN = ans;
for(int i = ;i <= n;i++){
MIN += n - (a[i] + ) - (a[i]);
ans = min(MIN,ans);
}
printf("%d\n",ans);
}
return ;
}

HDU 1394 线段树or 树状数组~的更多相关文章

  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 1166 敌兵布阵 (数状数组,或线段树)

    题意:... 析:可以直接用数状数组进行模拟,也可以用线段树. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000&quo ...

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

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

  5. hdu 1394 线段树

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

  6. HDU 2492 Ping pong (数状数组)

    Ping pong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

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

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

  8. hdu 1394(线段树) 最小逆序数

    http://acm.hdu.edu.cn/showproblem.php?pid=1394 给出一列数组,数组里的数都是从0到n-1的,在依次把第一个数放到最后一位的过程中求最小的逆序数 线段树的应 ...

  9. hdu 1394 线段树计算逆序数

    线段树计算逆序数的原理: 用线段树来统计已插入的数的个数(所以要保证最大的那个数不能太大,否则数组都开不了),然后每插入一个数,就查询比插入的数大的个数,累加即可. 这个题还有一个特点就是,题目给的是 ...

随机推荐

  1. 中南大学2019年ACM寒假集训前期训练题集(基础题)

    先写一部分,持续到更新完. A: 寒衣调 Description 男从戎,女守家.一夜,狼烟四起,男战死沙场.从此一道黄泉,两地离别.最后,女终于在等待中老去逝去.逝去的最后是换尽一生等到的相逢和团圆 ...

  2. HDU—4463 Outlets 最小生成树

    In China, foreign brand commodities are often much more expensive than abroad. The main reason is th ...

  3. Go:数组

    package main import "fmt" func main() { // 定义数组的方式 var array1 [3]int array2 := [3]int{} fm ...

  4. java 反射---学习笔记

    一.java的动态性 反射机制 动态编译 动态执行JavaScript代码 动态字节码操作 二.动态语言 动态语言 程序运行时,可以改变程序结构或变量类型,典型的语言:python.ruby.java ...

  5. JqueryValidate 修改 为根据ID验证

    <!--修改validate根据ID验证 --> <script type="text/javascript"> if ($.validator) { $. ...

  6. 集训第六周 数学概念与方法 概率 N题

    N - 概率 Time Limit:4000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status ...

  7. 使用C++调用pytorch模型(Linux)

    前言 模型转换思路通常为: Pytorch -> ONNX -> TensorRT Pytorch -> ONNX -> TVM Pytorch -> 转换工具 -> ...

  8. 学习javascript中的事件——事件处理程序

    事件就是用户或浏览器自身执行的某种动作.诸如 click.load 和 mouseover ,都是事件的名字.而响应某个事件的函数就叫做事件处理程序(或事件侦听器).事件处理程序的名字以“on”开头, ...

  9. Session与Token的区别

    1. 为什么要有session的出现?答:是由于网络中http协议造成的,因为http本身是无状态协议,这样,无法确定你的本次请求和上次请求是不是你发送的.如果要进行类似论坛登陆相关的操作,就实现不了 ...

  10. MySQL SQL语句 生成32位 UUID

    在运营中,有时会碰到线下下单,线下注册,需要在数据库对其数据批量生成导入的场景. 此时如果你的数据表主键并不是Int整型自动递增而是32位的UUID这种情况该怎么办呢? MySQL 其实实现了UUID ...