【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原创,转载请注明出处)

posted on 2010-11-09 21:57  saltless  阅读(835)  评论(0编辑  收藏  举报

导航