• 求逆序数(the number of inversions)(数学)


    1.用树状数组求逆序数

    缺点:只能对整数求逆序数

     1 #include "TreeArray.h"
     2 /*
     3 算法:
     4 由树状数组求逆序对。加入元素i即把以元素i为下标的a[i]值+1,从队尾到队首入队,
     5 每次入队时逆序对数 += getsum(i - 1),即下标比它大的但是值比它小的元素个数。
     6 因为树状数组不能处理下标为0的元素,每个元素进入时+1,相应的其他程序也要相应调整。
     7 求出原始的序列的逆序对个数后每次把最前面的元素移到队尾,逆序对数即为
     8 原逆序对数+比i大的元素个数-比i小的元素个数,因为是0..n,容易直接算出
     9 */
    10 int NiXuShu(int Array[], int n)
    11 {
    12     TreeArray ta(1);
    13     ta.clear();
    14     int i, sum = 0;
    15     for (i = n-1; i >= 0; i --)
    16     {
    17         ta.modify(Array[i]+1, 1);
    18         sum = sum + ta.sum(Array[i]);
    19     }
    20     return sum;
    21 }
    View Code

    这种方法理解的还不是很透彻,还是要再理解一下。 

    2.用归并排序求逆序数

    缺点:会改变数组中的值

     1 # include <iostream>
     2 # define N 500010
     3 using namespace std;
     4 
     5 long long cnt;
     6 int a[N], t[N];
     7 void merge(int s1, int e1, int s2, int e2)
     8 {
     9     int p1 = s1, p2 = s2, p=0;
    10     while(p1 <= e1 && p2 <= e2)
    11     {
    12         if(a[p1] <= a[p2])
    13         {
    14             t[p++] = a[p1++];
    15         }
    16         else
    17         {
    18             t[p++] = a[p2++];
    19             cnt += e1-p1+1;
    20         }
    21     }
    22     while(p1<=e1)
    23     {
    24         t[p++] = a[p1++];
    25     }
    26     while(p2 <= e2)
    27     {
    28         t[p++] = a[p2++];
    29     }
    30     for(int i = s1; i <= e2; i++)
    31     {
    32         a[i] = t[i-s1];
    33     }
    34 }
    35 void mergesort(int s, int e)
    36 {
    37     if(s < e)
    38     {
    39         int m = (s+e)/2;
    40         mergesort(s, m);
    41         mergesort(m+1, e);
    42         merge(s, m, m+1, e);
    43     }
    44 }
    45 int main(void)
    46 {
    47     int n;
    48     while(cin >> n, n)
    49     {
    50         cnt = 0;
    51         for(int i = 0; i < n; i++)
    52             cin >> a[i];
    53         mergesort(0, n-1);
    54         cout << cnt << endl << endl;
    55     }
    56 
    57     return 0;
    58 }
    View Code

    用cin的话跑时会很多,还是scanf好。


     

  • 相关阅读:
    你应该了解Nginx的7个原因
    linux 中php以及nginx的重启命令
    HTTP 长连接和短连接
    git常用命令
    Linux 防火墙开放特定端口 (iptables)
    redis配置文件相关
    关于解决emoji表情的存储
    文件内容统计——Linux wc命令
    Git 服务器搭建
    关于微信二次分享,描述变链接的解决方法(一)----文档说明
  • 原文地址:https://www.cnblogs.com/Silence-AC/p/3257368.html
Copyright © 2020-2023  润新知