zoukankan      html  css  js  c++  java
  • HDU 1394 (逆序数) Minimum Inversion Number

    原来求逆序数还可以用线段树,涨姿势了。

    首先求出原始序列的逆序数,然后递推每一个序列的逆序数。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int maxn = 20000 + 10;
     7 
     8 int n, p, qL, qR;
     9 int sum[maxn], a[5000 + 10];
    10 
    11 void update(int o, int L, int R)
    12 {
    13     if(L == R) { sum[o]++; return; }
    14     int M = (L + R) / 2;
    15     if(p <= M) update(o*2, L, M);
    16     else update(o*2+1, M+1, R);
    17     sum[o] = sum[o*2] + sum[o*2+1];
    18 }
    19 
    20 int query(int o, int L, int R)
    21 {
    22     if(qL <= L && qR >= R) return sum[o];
    23     int ans = 0;
    24     int M = (L + R) / 2;
    25     if(qL <= M) ans += query(o*2, L, M);
    26     if(qR > M) ans += query(o*2+1, M+1, R);
    27     return ans;
    28 }
    29 
    30 int main()
    31 {
    32     //freopen("in.txt", "r", stdin);
    33 
    34     while(scanf("%d", &n) == 1)
    35     {
    36         memset(sum, 0, sizeof(sum));
    37 
    38         for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    39         int inv = 0;
    40         for(int i = 0; i < n; i++)
    41         {
    42             p = a[i];
    43             qL = a[i]; qR = n - 1;
    44             inv += query(1, 0, n - 1);
    45             update(1, 0, n - 1);
    46         }
    47         int ans = inv;
    48         for(int i = 0; i < n; i++)
    49         {
    50             inv = inv + n - a[i]*2 - 1;
    51             ans = min(ans, inv);
    52         }
    53         printf("%d
    ", ans);
    54     }
    55 
    56     return 0;
    57 }
    线段树

    既然要求逆序数了,干脆树状数组,归并排序也都试一试。

    由于树状数组lowbit的特点,所以数组下标是从1开始的。但是树状数组要比线段树好写很多。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int maxn = 5000 + 10;
     7 int n;
     8 int a[maxn], s[maxn];
     9 
    10 inline int lowbit(int x) { return x&(-x); }
    11 
    12 int sum(int x)
    13 {
    14     int ans = 0;
    15     while(x > 0) { ans += s[x]; x -= lowbit(x); }
    16     return ans;
    17 }
    18 
    19 void add(int x, int d)
    20 {
    21     while(x <= n) { s[x] += d; x += lowbit(x); }
    22 }
    23 
    24 int main()
    25 {
    26     //freopen("in.txt", "r", stdin);
    27 
    28     while(scanf("%d", &n) == 1)
    29     {
    30         memset(s, 0, sizeof(s));
    31         for(int i = 0; i < n; i++) { scanf("%d", &a[i]); a[i]++; }
    32         int inv = 0;
    33         for(int i = 0; i < n; i++)
    34         {
    35             inv += sum(n) - sum(a[i]);
    36             add(a[i], 1);
    37         }
    38         int ans = inv;
    39         for(int i = 0; i < n; i++)
    40         {
    41             inv = inv + n + 1 - a[i]*2;
    42             ans = min(ans, inv);
    43         }
    44         printf("%d
    ", ans);
    45     }
    46 
    47     return 0;
    48 }
    树状数组

    下面是归并排序,_(:зゝ∠)_

    代码不长,但是感觉还是挺容易写错的。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int maxn = 5000 + 10;
     7 int n, inv;
     8 int a[maxn], b[maxn], T[maxn];
     9 
    10 void MergeSort(int x, int y)
    11 {
    12     if(y - x > 1)
    13     {
    14         int m = (x + y) / 2;
    15         int p = x, q = m, i = x;
    16         MergeSort(x, m); MergeSort(m, y);
    17         while(p < m || q < y)
    18         {
    19             if(q >= y || (p < m && a[p] <= a[q])) T[i++] = a[p++];
    20             else { T[i++] = a[q++]; inv += m - p; }
    21         }
    22         for(i = x; i < y; i++) a[i] = T[i];
    23     }
    24 }
    25 
    26 int main()
    27 {
    28     //freopen("in.txt", "r", stdin);
    29 
    30     while(scanf("%d", &n) == 1)
    31     {
    32         for(int i = 0; i < n; i++) { scanf("%d", &a[i]); b[i] = a[i]; }
    33         inv = 0;
    34         MergeSort(0, n);
    35         int ans = inv;
    36         for(int i = 0; i < n; i++)
    37         {
    38             inv = inv + n - 1 - b[i]*2;
    39             ans = min(ans, inv);
    40         }
    41         printf("%d
    ", ans);
    42     }
    43 
    44     return 0;
    45 }
    归并排序
  • 相关阅读:
    Milk 结构体
    Milk 结构体
    Repeating Decimals, ACM/ICPC World Finals 1990, UVa202
    Repeating Decimals, ACM/ICPC World Finals 1990, UVa202
    DNA Consensus String, ACM/ICPC Seoul 2006, UVa1368
    DNA Consensus String, ACM/ICPC Seoul 2006, UVa1368
    Crossword Answers, ACM/ICPC World Finals 1994, UVa232
    【编程技巧】 iOS 5的StoryBoard(故事板)的一些用法
    【开发技术】storyboard和nib的差别
    【编程技巧】ExtJs 设置GridPanel表格文本垂直居中
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4456563.html
Copyright © 2011-2022 走看看