部分经典算法

双关键字快排

procedure swap(a,b:longint);
var t:longint;
begin
 for i:=1 to 3 do
  begin
   t:=x[a,i];
   x[a,i]:=x[b,i];
   x[b,i]:=t;
  end;
end;

procedure sort(l,r: longint);
var i,j,x1,x2,y: longint;
begin
 i:=l; j:=r; x1:=x[(l+r) div 2,1]; x2:=x[(l+r) div 2,2];
 repeat
  while (x[i,1]<x1)or((x[i,1]=x1)and(x[i,2]<x2)) do inc(i);
  while (x1<x[j,1])or((x[j,1]=x1)and(x[j,2]>x2)) do dec(j);
  if not(i>j) then
   begin
    swap(i,j);
    inc(i); dec(j);
   end;
 until i>j;
 if l<j then sort(l,j);
 if i<r then sort(i,r);
end;

归并排序

逆序对

var
 x,y:array[0..2000000]of longint;
 i,j,k:longint;
 n,len:longint;
 ans:int64;
procedure sort(l,r:longint);
var i,j,mid:longint;
begin
 if l>=r then exit;
 mid:=(l+r)>>1;
 sort(l,mid);
 sort(mid+1,r);
 i:=l; j:=mid+1; len:=l-1;
 while (i<=mid)or(j<=r) do
  if (j>r)or((i<=mid)and(x[i]<=x[j]))
  then begin inc(len); y[len]:=x[i]; inc(i); end
  else begin inc(len); y[len]:=x[j]; inc(j); inc(ans,mid-i+1);  {inc是用来算逆序对的} end;
 for i:=l to r do
  x[i]:=y[i];
end;

begin
 readln(N);
 for i:=1 to n do
  read(x[i]);
 ans:=0;
 sort(1,n);
 writeln(ans);
end.

树状数组

  • 先离散化,从后向前每次先查询,再把自己加入树状数组
  • 加入时是把y[x[i]]+1
var
 x,y:array[0..1000005]of longint;
 i,j,k:longint;
 n,maxn:longint;
 ans:int64;
function query(a:longint):int64;
var tt:int64;
begin
 tt:=0;
 while a>0 do
  begin
   inc(tt,y[a]);
   dec(a,a and(-a));
  end;
 exit(tt);
end;

procedure update(a:longint);
begin
 while a<=maxn do
  begin
   inc(y[a]);
   inc(a,a and(-a));
  end;
end;

begin
 readln(n); maxn:=0;
 for i:=1 to n do
  begin read(x[i]); if x[i]>maxn then maxn:=x[i]; end;
 ans:=0;
 for i:=n downto 1 do
  begin
   inc(ans,query(x[i]-1));
   update(x[i]);
  end;
 writeln(ans);
end.

堆排序

var
 n,i:longint;
 x,heap:array[0..1000000]of longint;
procedure shai(z:longint);
var tt,a,b,s:longint;
begin
 tt:=z;
 while (heap[tt*2]<>-maxlongint)or(heap[tt*2+1]<>-maxlongint) do
  begin
   a:=tt*2; b:=a+1;
   if (heap[a]>heap[tt])and(heap[a]>=heap[b]) then begin s:=heap[a]; heap[a]:=heap[tt]; heap[tt]:=s; tt:=a; end else
   if (heap[b]>heap[tt])and(heap[b]>=heap[a]) then begin s:=heap[b]; heap[b]:=heap[tt]; heap[tt]:=s; tt:=b; end
   else break;
  end;
end;

procedure prepare;
begin
 readln(n);
 for i:=1 to 5*n do
  heap[i]:=-maxlongint;
 for i:=1 to n do
  read(heap[i]);
end;

begin
 prepare;
 heap[0]:=n;
 for i:=(n div 2) downto 1 do
  shai(i);
 while heap[0]<>1 do
  begin
   inc(x[0]); x[x[0]]:=heap[1];
   dec(heap[0]); heap[1]:=0; shai(1);
  end;
 x[n]:=heap[1];
 for i:=n downto 2 do
  write(x[i],' ');
 writeln(x[1]);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值