📘
Introduction_to_Algorithms
  • Introduction
  • 第6章:堆排序
    • 练习题
    • 思考题
      • 6-3 Young
  • 第7章:快速排序
    • 练习题
    • 思考题
      • 7-6 对区间的模糊排序
  • 第8章:线性时间排序
    • 练习题
      • 8.3-4 O(n)时间内对[0..n^-1]之间的n个数排序
    • 思考题
      • 8-3 排序不同长度的数据项
  • 第9章 排序和顺序统计学算法导论
    • 练习题
      • 9.1-1
      • 9.3-3 快速排序-最坏时间O(nlgn)
      • 9.3-6 nlgk时间求k分位数
      • 9.3-8 求两个数组的中位数
    • 思考题
      • 9-2-c-带权中位数
  • 第10章:栈和队列
    • 10.1 栈和队列
      • 练习题
      • 10.1-2 用一个数组实现两个栈
      • 10.1-5 双端队列
    • 10.2 链表
      • 练习题
      • 10.2-5 环形链表实现字典操作INSERT、DELETE、SEARCH
    • 10.3 指针和对象实现
      • 练习题
      • 10.3-4 紧凑的多重数组
    • 思考题
  • 第11章 散列表
  • [第12章]
    • [笔记和代码]
      • 12-2 基数树
  • 第14章
    • 笔记和代码
      • 14.3-6 MIN GAP
  • 第15章:动态规划
    • 练习题
    • 思考题
      • 15-2 整齐打印
      • 15-3 编辑距离
  • 第20章:斐波那契堆
    • 练习题
    • 思考题
  • ACM解题报告
    • 1043 八数码问题
    • 1053 Entropy
    • 1114 Piggy-Bank 完全背包
    • 1133 catalan数二维变种
    • 1166 敌兵布阵
    • 1281 棋盘游戏 二分匹配与增广链
    • 1394 Minimum Inversion Number
    • 1394 用线段树求逆序数
    • 1787 欧拉函数之在线算法
    • 2438 三分查找
    • 2473 Junk-Mail Filter 并查集的删除
    • 2824 欧拉公式之打表算法
    • 2855 Fibonacci Check-up 矩阵的应用
    • 2642 Stars 二维树状数组
    • 2888 二维RMQ
    • 3033 分组背包之每组至少选一
    • 3307 A^B = C mod D,已知A,C,D,求解B
    • 3465 Life is a Line 用归并排序求逆序数
    • 3483 A Very Simple Problem 数论+矩阵的应用
    • 3518 后缀数组
    • 3579 中国剩余定理(ACM/不互质的情况)
    • 后缀数组
    • B-树
    • 排序算法总结
Powered by GitBook
On this page
  • 题目链接
  • 题目解释
  • 算法
  • 关于树状数组
  • 由树状数组求原始数组的逆序对
  • 依次求各种序列的逆序对数
  • 代码
  1. ACM解题报告

1394 Minimum Inversion Number

Previous1281 棋盘游戏 二分匹配与增广链Next1394 用线段树求逆序数

Last updated 3 years ago

题目链接

Inversion Number, 树状数组

题目解释

对于一个由n个数字组成的序列,把它的队首m(0<=m<n)个元素移到队尾,求形成了另一个队列

长度为n的序列通过这种方式可以得到n种不同的序列,求这n个序列中逆序数最小的序列的逆序数

算法

关于树状数组

参考《树状数组》

由树状数组求原始数组的逆序对

对原始序列中的所有元素,其元素值+1(因为树状数组不能处理0,所有必须保证要处理的序列中没有值为0的元素)

对原始序列中的元素,从队尾至队首,依次对每个元素做以下操作:

1.把该元素q加入到树状数组a中,即a.modify(q, 1)

2.计算在q之前加入到a且比q小的元素个数,即ret = getsum(i - 1)

3.该序列的逆序对数 += ret

当序列中的元素全部处理完,就能计算出该序列的逆序对数了

依次求各种序列的逆序对数

令f(m)为把原始序列s的前m个元素移到队尾得到的序列的逆序对数

现在已求出f(0)

第一个元素q移到队尾后,f(1)=f(0)+比q大的元素个数-比q小的元素个数

依次类推,f(m) = f(m-1) + 比s[m-1]大的元素个数 - 比s[m-1]小的元素个数

这样就可以依次计算出所有序列的逆序对数了

代码

    #include <stdio.h>  
    #define MAXN 10000  

    int c[MAXN],a[MAXN],n;  

    int min(int a,int b)  
    {  
        if (a < b) return a;  
        else return b;  
    }  

    int lowbit(int i)  
    {  
        return i & -i;  
    }  


    void update(int i,int x)  
    {  
        while (i <= n)  
        {  
            c[i] += x;  
            i += lowbit(i);  
        }  
    }  

    int getsum(int x)  
    {  
        int sum = 0;  
        while (x > 0)  
        {  
            sum += c[x];  
            x -= lowbit(x);  
        }  
        return sum;  
    }  

    int main()  
    {  
        while (scanf("%d", &n) == 1)  
        {  
            for (int i = 1; i <= n; i++)  
                c[i] = 0;  
            int sum = 0;  
            for (int i = 1; i <= n; i ++)  
            {  
                scanf ("%d", &a[i]);  
            }  
            for (int i = n; i >= 1; i --)  
            {  
                update (a[i] + 1, 1);  
                sum += getsum (a[i]);  
            }  
            int ans = sum;  
            for (int i = 1; i <= n; i++)  
            {  
                sum = sum - a[i] + (n - a[i] - 1);  
                ans = min(ans, sum);  
            }  
            printf("%d\n", ans);  
        }  
        return 0;  
    }
http://acm.hdu.edu.cn/showproblem.php?pid=1394