排序算法练习(二)

分治算法_求逆序对

AYYZOJ p1434

【问题描述】
  给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目。
【输入格式】
  第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。
【输出格式】
  所有逆序对总数。
【输入样例】
  4
  3
  2
  3
  2
【输出样例】
  3
【数据范围】
  N<=10^5,Ai<=10^5。

思路:与归并排序联系起来。

分析:

    归并排序是将序列a[1,H]分成两部分——a[1,mid]和a[mid+1,H]分别进行归并排序,然后将这两部分合并起来。

    在合并的过程中(设1<=i<=mid,mid+1<=j<=H),

          当a[i]<=a[j]时,并不产生逆序对;

          当a[i]>a[j]时,在前半部分a[1,mid]中,比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid-i+1.(i..mid 共有mid-i+1个数)

    因此,可以在归并排序中的合并过程中计算逆序对的数量。

 1 var
 2   a,r:array[1..100000] of longint;
 3   i,n:longint;ans:int64;
 4 procedure mergesort(s,t:longint);
 5   var
 6     m,i,j,k:longint;
 7   begin
 8     if s=t then exit;
 9     m:=(s+t) div 2;
10     mergesort(s,m);
11     mergesort(m+1,t);
12     i:=s;
13     j:=m+1;
14     k:=s;
15     while (i<=m) and (j<=t) do
16       if a[i]<=a[j] then
17         begin r[k]:=a[i];inc(i);inc(k);end
18       else
19         begin ans:=ans+m-i+1; r[k]:=a[j]; inc(j); inc(k);end;
20     while i<=m do begin r[k]:=a[i]; inc(i); inc(k);end;
21     while j<=t do begin r[k]:=a[j]; inc(j); inc(k);end;
22     for i:=s to t do a[i]:=r[i];
23   end;
24 begin
25   readln(n);
26   for i:=1 to n do readln(a[i]);
27   mergesort(1,n);
28   writeln(ans);
29 end.

排序算法_车厢重组

AYYZOJ p1437

这题的描述让人一眼觉得就是冒泡排序,老师说正解应该是归并,可是数据太弱,冒泡就水过了。

 1 program p1437;
 2 var
 3  n,i,j,t,k:longint;
 4  a:array[1..10000] of longint;
 5  flag:boolean;
 6 begin
 7  readln(n);
 8  for i:=1 to n do read(a[i]);
 9   for j:=1 to n-1 do
10    begin
11     flag:=true;
12     for i:=1 to n-j do
13     if a[i]>a[i+1] then begin
14        t:=a[i];a[i]:=a[i+1];a[i+1]:=t; inc(k);
15         flag:=false; end;
16     if flag then break;
17    end;
18  write(k);
19 end.
冒泡排序
原文地址:https://www.cnblogs.com/vacation/p/5180634.html