最小交换次数即求逆序对数。
但应当是某一个数组中每个元素目标位置的新数组的逆序对数(这样才符合“交换”)
求逆序对可以用树状数组O(3nlogn)
program march;
var a,b,c,m,key:array[1..100000]of longint;
i,n:longint;
ans:int64;
function lowbit(x:longint):longint;
begin
lowbit:=x and (-x);
end;
procedure qsort(x,y:longint);
var i,j,mid,t:longint;
begin
i:=x;j:=y;
mid:=a[(x+y) div 2];
repeat
while a[i]<mid do i:=i+1;
while a[j]>mid do j:=j-1;
if i<=j then
begin
t:=a[i];a[i]:=a[j];a[j]:=t;
t:=m[i];m[i]:=m[j];m[j]:=t;
i:=i+1;j:=j-1;
end;
until i>j;
if x<j then qsort(x,j);
if i<y then qsort(i,y);
end;
procedure qsort1(x,y:longint);
var i,j,t,mid:longint;
begin
i:=x;j:=y;
mid:=b[(x+y) div 2];
repeat
while b[i]<mid do i:=i+1;
while b[j]>mid do j:=j-1;
if i<=j then
begin
t:=b[i];b[i]:=b[j];b[j]:=t;
t:=m[i];m[i]:=m[j];m[j]:=t;
i:=i+1;j:=j-1;
end;
until i>j;
if i<y then qsort1(i,y);
if x<j then qsort1(x,j);
end;
procedure updata(x,n:longint);
begin
while x<=n do
begin
c[x]:=c[x]+1;
x:=x+lowbit(x);
end;
end;
function getsum(x:longint):longint;
var s:longint;
begin
s:=0;
while x>0 do
begin
s:=s+c[x];
x:=x-lowbit(x);
end;
getsum:=s;
end;
begin
read(n);
for i:=1 to n do begin m[i]:=i;read(a[i]);end;
qsort(1,n);
for i:=1 to n do a[m[i]]:=i;//对a离散化
for i:=1 to n do begin read(b[i]);m[i]:=i;end;
qsort1(1,n);
for i:=1 to n do b[m[i]]:=i;//对b离散化
//确定b目标位置
for i:=1 to n do key[a[i]]:=i;
for i:=1 to n do b[i]:=key[b[i]];
//求逆序对数
for i:=1 to n do
begin
updata(b[i],n);//c[]以元素大小为下标
ans:=(ans+i-getsum(b[i])) mod 99999997;
end;
write(ans);
end.
这题为什么不可以先将a、b按a从小到大排序,再将b离散化再求b的逆序对呢?因为这样破坏了移动顺序,答案有问题。