火柴排队(codevs 3286)题解

【问题描述】

涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:,其中 ai表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第 i 个火柴的高度。每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。

【样例输入1】

    4 
    2 3 1 4 
    3 2 1 4

【样例输出1】

    1

【样例输入2】

    4 
    1 3 4 2 
    1 7 2 4

【样例输出2】

    2

【解题思路】

     本题为NOIP2013提高组day1第二题,初看这道题目,天啊,好难!又要移动两个序列,又要找最小步数。其实仔细研究一下,会发现一点也不难。

    首先,不需要移动两个序列,移动一个序列是等价的(最终结果相同),因此,我们只需移动一个序列。

   其次,本题的解法是非常简单的,我们可以确定,要使两个队列的距离最小,那么需要两个队列每一个位置上的高度差最小,因此,我们只需要把两个序列的高度排列的顺序换到相同就行了。我们来研究一下样例1:

   样例一中2、3、1、4从小到大排列后变成了1、2、3、4,1、2、3、4在序列中所对应的序号为3、1、2、4,因此,根据我们刚才得出的解法,只要把序列二的从小到大的排列放在3、1、2、4的位置上就行了。现在我们将序列二从小到大排列,变成了1、2、3、4,在序列二中所对应的序号为3、2、1、4,我们新建一个序列三,设序列三为c,c[i]表示在序列二中序号为i的数需要放在第c[i]个,因此,序列三为2、1、3、4,即对于第x个数,它在序列二所对的序号为i,在序列一中的序号为c[i],这样,c数组就出来了,剩下的事情就是求逆序对个数了,注意边求边取模即可。

【代码实现】

 1 type rec=record

 2      xh,data:longint;

 3 end;

 4      arr=array[0..100010] of rec;

 5 var a,b:arr;

 6     c,t:array[0..100010] of longint;

 7     ans,i,j,n,min,minj,y:longint;

 8 procedure sort(l,r:longint;var a:arr);

 9       var

10          i,j,x:longint;

11          y:rec;

12       begin

13          i:=l;

14          j:=r;

15          x:=a[(l+r) div 2].data;

16          repeat

17            while a[i].data<x do

18             inc(i);

19            while x<a[j].data do

20             dec(j);

21            if not(i>j) then

22              begin

23                 y:=a[i];

24                 a[i]:=a[j];

25                 a[j]:=y;

26                 inc(i);

27                 j:=j-1;

28              end;

29          until i>j;

30          if l<j then

31            sort(l,j,a);

32          if i<r then

33            sort(i,r,a);

34       end;

35 procedure gb(l,r:longint);

36 var i,j,p,mid:longint;

37 begin

38  if l=r then exit;

39  mid:=(l+r)div 2;

40  gb(l,mid);

41  gb(mid+1,r);

42  i:=l;p:=l;j:=mid+1;

43  while(i<=mid)and(j<=r)do

44   if c[i]<=c[j] then

45    begin

46     t[p]:=c[i];inc(p);inc(i);

47    end

48   else

49    begin

50     ans:=(ans+mid-i+1)mod 99999997;t[p]:=c[j];inc(p);inc(j);

51    end;

52  while i<=mid do

53   begin

54    t[p]:=c[i];inc(p);inc(i);

55   end;

56  while j<=r do

57   begin

58    t[p]:=c[j];inc(p);inc(j);

59   end;

60  for i:=l to r do

61   c[i]:=t[i];

62 end;

63 begin

64  readln(n);

65  for i:=1 to n do

66   begin

67    read(a[i].data);

68    a[i].xh:=i;

69   end;

70  for i:=1 to n do

71   begin

72    read(b[i].data);

73    b[i].xh:=i;

74   end;

75  sort(1,n,a);

76  sort(1,n,b);

77  for i:=1 to n do

78   c[b[i].xh]:=a[i].xh;

79  gb(1,n);

80  writeln(ans);

81 end.

 

你可能感兴趣的:(code)