您的位置:首页 > 其它

noip2013火柴排队

2014-10-16 21:11 225 查看
最小交换次数即求逆序对数。

但应当是某一个数组中每个元素目标位置的新数组的逆序对数(这样才符合“交换”)

求逆序对可以用树状数组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的逆序对呢?因为这样破坏了移动顺序,答案有问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: