【Nov 8 P2,逆序对】最接近神的人
【题目描述】
破解了符文之语,小 FF开启了通往地下的道路。当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一副古代人进行某种活动的图案。而石门上方用古代文写着“神的殿堂“。小 FF猜想里面应该就有王室的遗产了。但现在的问题是如何打开这扇门……
仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的。而最聪明的人往往通过一种仪式选拔出来。仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即交换序列中相邻的两个元素。而用最少的交换次数使原序列变成不下降序列的人即是下一任智者。
小 FF发现门上同样有着 n个数字。于是他认为打开这扇门的秘诀就是找到让这个序列变成不下降序列所需要的最小次数。但小 FF不会……只好又找到了你,并答应事成之后与你三七分……
【输入格式】
第一行为一个整数 n,表示序列长度
第二行为 n个整数,表示序列中每个元素。
【输出格式】
一个整数 ans,即最少操作次数。
【输入样例】
4
2 8 0 3
【输出样例】
3
样例说明:开始序列为 2 8 0 3,目标序列为 0 2 3 8,可进行三次操作得目标序列:
1.Swap(8,0): 2 0 8 3
2.Swap(2, 0): 0 2 8 3
3.Swap(8, 3): 0 2 3 8
【数据范围】
对于 30%的数据 1<= n <= 10^4.
对于 100%的数据 1 <= n <= 5*10^5; -maxlongint <= A[i ]<= maxlongint
这道题和冒泡排序很像,总体想法就是把大和小的换位置,将点冒到它该在的位置上。这时,我们就想到了逆序对。显然,逆序对的个数就是本题的解,因为只要有一个逆序对,就要交换一次。我们知道,求解逆序对的过程就是一个改装的归并排序,逆序对找完后数组也就有序了。这样,两个问题就统一到了一起。
参考代码:
program sophist; var n:longint; i,j:longint; tot:int64; a,b:array[0..500000]of longint; procedure msort(l,r:longint); //寻找逆序对 var i,j,m,k:longint; begin if l>=r then exit; m:=(l+r)shr 1; msort(l,m); msort(m+1,r); i:=l; j:=m+1; k:=l; repeat if a[i]>a[j] then begin tot:=tot+m-i+1; b[k]:=a[j]; inc(j); inc(k); end else begin b[k]:=a[i]; inc(i); inc(k); end; until(i>m)or(j>r); while i<=m do begin b[k]:=a[i]; inc(i); inc(k); end; while j<=r do begin b[k]:=a[j]; inc(j); inc(k); end; for i:=l to r do a[i]:=b[i]; //更新a数组 end; begin readln(n); for i:=1 to n do read(a[i]); msort(1,n); writeln(tot); end.
本文地址:http://www.cnblogs.com/saltless/archive/2010/11/09/1873111.html
(saltless原创,转载请注明出处)