program 19-5-5; const MAX = 100000; type TCisla = array[1..MAX] of LongInt; { Hlavní funkce programu. Pracuje na principu algoritmu merge sort a přitom počítá inverze. Parametry: main - hlavní pole s čísly, tmp - pomocné pole, i,j - tříděný rozsah } function merge(var main, tmp: TCisla; i, j: LongInt) : Integer; var mid, count: LongInt; a, b, res: LongInt; begin merge := 0; if (i >= j) then Exit; { prázdný interval => končíme } { určíme střed tříděného intervalu a metodou rozděl a panuj spočítáme podúlohy } mid := (i+j) div 2; count := merge(tmp, main, i, mid); count := merge(tmp, main, mid+1, j) + count; { nyní slijeme setříděné poloviny } a := i; b := mid+1; { indexy v setříděných polovinách } res := i; { index ve výsledném poli } while (a <= mid) and (b <= j) do begin { sléváme, dokud jeden z indexů nedojede do konce svého úseku } if (tmp[a] > tmp[b]) then begin { "porucha" v uspořádání - v druhé půlce je menší prvek } count := count + (mid-a+1); { přičteme tolik inverzí, kolik prvků zbývá v 1. části } main[res] := tmp[b]; inc(b); end else begin { prvek z 1. části je menší - žádné inverze nepřičítáme } main[res] := tmp[a]; inc(a); end; inc(res); end; { zkopírujeme zbytky slévaných částí (jsou-li nějaké) } while (a <= mid) do begin main[res] := tmp[a]; inc(a); inc(res); end; while (b <= j) do begin main[res] := tmp[b]; inc(b); inc(res);end; merge := count; end; var F : Text; N, i : LongInt; cisla, cisla2 : TCisla; { čísla jsou alokovaná staticky (pro zpřehlednění kódu) } begin Assign(F, 'cisla.in'); { Načtení vstupu } Reset(F); ReadLn(F, N); { počet čísel N } for i := 1 to N do begin Read(F, cisla[i]); cisla2[i] := cisla[i]; end; Close(F); Write( merge(cisla, cisla2, 1, N) ); { spočítáme počet inverzí a rovnou jej vytiskneme na výstup } end.