zoukankan      html  css  js  c++  java
  • 逆序数 之 hdu 1394 Minimum Inversion Number

    //  [7/29/2014 Sjm]
    /*
    时间复杂度: O(nlogn)
    实现方式:树状数组 or 线段树
    逆序数:
    在一个排列中,若一对数,前面的数大于后一个数(即位置顺序和大小顺序相反),就称它们为一个逆序。排列中,逆序的总数即称为此排列的逆序数。
     
    求逆序数方法:
    树状数组 或 线段树
    (1)树状数组实现方法:参见 树状数组优化 之 uva299 中的法一
    (2)线段树实现方法:在每插入一个数据之前,计算有多少之前插入的数大于它,累计结果,即所要求的逆序数。
     
    但是,由于此题要求所有转换数字串的逆序数,选出最小值,若用 O(n^2logn) 的方法超时。。。故需优化。。。
    优化方法(所举例子是指有n个数,从1到n,和题目略有不同):
    假设以已求出 a1, a2, ..., an-1, an 排列的逆序数为sum,
    	若将此数字串转换为 a2, a3, ..., an, a1 
    	则逆序数必然增加 n-a1 (因为此时有 (n-a1) 个比a1大的数在前面),
    	同时与未转换的字符串相比,逆序数又减少了 (a1-1) 个 (因为此时有 (a1-1) 个比a1小的数在前面)
    	故而每转换一次后,sum += (n-a1-(a1-1))
     
    由此可求出答案。。。。(我在做题时,默认将输入的值做 +1 处理)。
    */
     1 // 树状数组
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <algorithm>
     7 using namespace std;
     8 const int MAX_N = 5005;
     9 int n, bit[MAX_N], arr[MAX_N];
    10 
    11 int mySum(int i) {
    12     int sum = 0;
    13     while (i > 0) {
    14         sum += bit[i];
    15         i -= (i&(-i));
    16     }
    17     return sum;
    18 }
    19 
    20 void myAdd(int i, int x) {
    21     while (i <= n) {
    22         bit[i] += x;
    23         i += (i&(-i));
    24     }
    25 }
    26 
    27 void Solve() {
    28     memset(bit, 0, sizeof(bit));
    29     int sum = 0;
    30     for (int i = 0; i < n; ++i) {
    31         sum += (i - mySum(arr[i] + 1));
    32         myAdd(arr[i] + 1, 1);
    33     }
    34     int ans = sum;
    35     for (int i = 0; i < n; ++i) {
    36         sum += (n - (arr[i] + 1) - (arr[i] + 1) + 1);
    37         ans = min(ans, sum);
    38     }
    39     printf("%d
    ", ans);
    40 }
    41 
    42 int main()
    43 {
    44 
    45     //freopen("input.txt", "r", stdin);
    46     //freopen("output.txt", "w", stdout);
    47     while (~scanf("%d", &n)) {
    48         for (int i = 0; i < n; ++i) {
    49             scanf("%d", &arr[i]);
    50         }
    51         Solve();
    52     }
    53     return 0;
    54 }
    
    
     1 // 线段树
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstdio>
     5 #include <algorithm>
     6 using namespace std;
     7 #define lson l, m, rt<<1
     8 #define rson m+1, r, rt<<1|1
     9 #define GetMid(l, r) l+((r-l)>>1)
    10 
    11 const int MAX_N = 5005;
    12 int n, Sum[MAX_N << 2], arr[MAX_N];
    13 
    14 void PushUp(int rt) { Sum[rt] = Sum[rt << 1] + Sum[rt << 1 | 1]; }
    15 
    16 void Build(int l, int r, int rt) {
    17     if (l == r) { Sum[rt] = 0; return; }
    18     int m = GetMid(l, r);
    19     Build(lson);
    20     Build(rson);
    21     PushUp(rt);
    22 }
    23 
    24 void Update(int pos, int val, int l, int r, int rt) {
    25     if (l == r) {
    26         Sum[rt] += val;
    27         return;
    28     }
    29     int m = GetMid(l, r);
    30     if (pos <= m) Update(pos, val, lson);
    31     else Update(pos, val, rson);
    32     PushUp(rt);
    33 }
    34 
    35 int Query(int L, int R, int l, int r, int rt) {
    36     if (L <= l && r <= R) { return Sum[rt]; }
    37     int ans = 0;
    38     int m = GetMid(l, r);
    39     if (L <= m) ans += Query(L, R, lson);
    40     if (m < R) ans += Query(L, R, rson);
    41     return ans;
    42 }
    43 
    44 int main()
    45 {
    46     //freopen("input.txt", "r", stdin);
    47     //freopen("output.txt", "w", stdout);
    48     int sum, ans;
    49     while (~scanf("%d", &n)) {
    50         Build(1, n, 1);
    51         sum = 0;
    52         for (int i = 0; i < n; ++i) {
    53             scanf("%d", &arr[i]);
    54             sum += Query(arr[i] + 1, n, 1, n, 1);
    55             int lll = Query(arr[i] + 1, n, 1, n, 1);
    56             Update(arr[i] + 1, 1, 1, n, 1);
    57         }
    58         ans = sum;
    59         for (int i = 0; i < n; ++i) {
    60             sum += (n - (arr[i] + 1) - (arr[i] + 1) + 1);
    61             ans = min(ans, sum);
    62         }
    63         printf("%d
    ", ans);
    64     }
    65     return 0;
    66 }


  • 相关阅读:
    Sql日期时间格式转换
    c#被指定为此窗体的 MdiParent 的窗体不是 MdiContainer?
    kmeans聚类分析
    C# VS2005打开没问题,但是运行解决方案时就整个自动关闭了
    PowerDesigner教程系列(一)概念数据模型
    PowerDesigner概念设计模型(CDM)中的3种实体关系
    spss clementine Twostep Cluster(两步聚类 二阶聚类)
    PowerDesigner教程系列(三)概念数据模型
    Kmeans聚类算法
    c# 中窗体居中代码怎么写?
  • 原文地址:https://www.cnblogs.com/shijianming/p/4140811.html
Copyright © 2011-2022 走看看