SSL 1198
题目描述
先给出逆序对的定义,对于一个给定的数列{An},如果有iAj,则称(i,j)为一逆序对.
求给出一个数列,求出这个数列包含多少个逆序对?
(说明一下啊,是从小到大逆序的)
题目分析
分治很难看出来,不过实质是用归并排序。
归并时,若有一个数与前面这个数逆序的话,那么毫无疑问,这个区间后面的数肯定都与它逆序。
原理化成代码就是:
if a[i],a[j]逆序时 then
记录变量:=记录变量+1+mid-位于前面的指针;
就这么简单
代码如下
var
n,i,s:longint;
a:array[1..10000]of longint;
procedure m(l,mid,h:longint);
var
i,j,k:longint;
b:array[1..10000]of longint;
begin
i:=l;j:=mid+1;fillchar(b,sizeof(b),#0);
k:=0;
while (i<=mid)and(j<=h) do
if a[i]>a[j] then
begin
s:=s+mid+1-i;
inc(k);
b[k]:=a[j];
inc(j);
end
else
begin
inc(k);
b[k]:=a[i];
inc(i);
end;
for i:=i to mid do begin inc(k);b[k]:=a[i]; end;
for i:=j to h do begin inc(k);b[k]:=a[i]; end;
for i:=l to h do a[i]:=b[i-l+1];
end;
procedure ms(l,h:longint);
var
mid:longint;
begin
if l<h then
begin
mid:=(l+h)div 2;
ms(l,mid);
ms(mid+1,h);
m(l,mid,h);
end;
end;
begin
readln(n);
for i:=1 to n do read(a[i]);
ms(1,n);
writeln(s);
end.