归并排序笔记

时间复杂度:稳定的O(nlogn)O(n log n)O(nlogn)
代码:

Var a,tmp:array[1..500005] of longint;
    i,n,s:longint;

procedure mergesort(l,r,mid:longint);
Var i,j,k:longint;
Begin
        i:=l;
        j:=mid+1;
        k:=l;
        while (i<=mid) and (j<=r) do
        Begin
                if a[i]<=a[j] then
                Begin
                        tmp[k]:=a[i];
                        i:=i+1;
                end
                else
                Begin
                        tmp[k]:=a[j];
                        j:=j+1;
                end;
                k:=k+1;
        end;

        while i<=mid do
        Begin
                tmp[k]:=a[i];
                i:=i+1;
                k:=k+1;
        end;
        while j<=r do
        Begin
                tmp[k]:=a[j];
                j:=j+1;
                k:=k+1;
        end;

        for i:=l to r do
        Begin
                a[i]:=tmp[i];
        end; writeln('/');
end;

procedure way(l,r:longint);
Var mid:longint;
Begin
        if l<r then
        Begin
                mid:=(l+r)>>1;
                way(l,mid);
                way(mid+1,r);
                mergesort(l,r,mid);
        end;
end;

Begin
        readln(n);
        for i:=1 to n do read(a[i]);
        s:=0;
        way(1,n);
        for i:=1 to n do write(a[i],' ');
end.

例题:
最接近神的人最接近神的人

题目描述
破解了符文之语,小 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 .

暴力超时,故选用归并排序
AC Code:

Var a,tmp:array[1..500005] of int64;
    n,ans:int64;
    i:longint;

procedure mergesort(l,r,mid:int64);
Var i,j,k:int64;
Begin
        i:=l;
        j:=mid+1;
        k:=l;
        while (i<=mid) and (j<=r) do
        Begin
                if a[i]<=a[j] then
                Begin
                        tmp[k]:=a[i];
                        i:=i+1;
                end
                else
                Begin
                        tmp[k]:=a[j];
                        j:=j+1;
                        ans:=ans+(mid-i+1);
                end;
                k:=k+1;
        end;

        while i<=mid do
        Begin
                tmp[k]:=a[i];
                i:=i+1;
                k:=k+1;
        end;
        while j<=r do
        Begin
                tmp[k]:=a[j];
                j:=j+1;
                k:=k+1;
        end;

        i:=l;
        while i<=r do
        Begin
                a[i]:=tmp[i];
                i:=i+1; 
        end;
end;

procedure way(l,r:int64);
Var mid:int64;
Begin
        if l<r then
        Begin
                mid:=(l+r)>>1;
                way(l,mid);
                way(mid+1,r);
                mergesort(l,r,mid);
        end;
end;

Begin
        readln(n);
        for i:=1 to n do read(a[i]);
        ans:=0;
        way(1,n);
        write(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值