史上最强大的模板练习题——JZOJ1149排序

题目大意

给定N个数,从小到大排序输出。
N<=2*10^5。

OJ的排序王——WerKeyTom_FTD将逐一把各个模板写上来。
模板顺序根据效率从小到大。

1、左偏树struct包装(状态117795)

我们可以使用左偏树,练习struct包装。

#include<cstdio>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200005;
int dl[maxn];
int i,j,k,l,r,t,n,m,tot,root;
struct left_heap{
    int tot,key[maxn],left[maxn],right[maxn],dis[maxn];
    int merge(int a,int b){
        if (!a) return b;
        if (!b) return a;
        if (key[a]>key[b]) a^=b^=a^=b;
        right[a]=merge(right[a],b);
        if (dis[right[a]]>dis[left[a]]) right[a]^=left[a]^=right[a]^=left[a];
        dis[a]=dis[right[a]]+1;
        return a;
    }
    int deletemin(int x){
        return merge(left[x],right[x]);
    }
    int add(int x){
        key[++tot]=x;
        return tot;
    }
} s;
int main(){
    scanf("%d",&n);
    s.dis[0]=-1;
    r=0;
    fo(i,1,n){
        scanf("%d",&t);
        r=r%n+1;
        dl[r]=s.add(t);
    }
    l=0;
    tot=0;
    while ((l%n+1)!=r){
        l=l%n+1;
        j=dl[l];
        l=l%n+1;
        k=dl[l];
        i=s.merge(j,k);
        r=r%n+1;
        dl[r]=i;
    }
    root=dl[r];
    fo(i,1,n){
        printf("%d\n",s.key[root]);
        root=s.deletemin(root);
    }
    return 0;
}

2、左偏树(状态106438)

这次没有用struct,直接打。
可以看出这题左偏树很快,效率前两个都是它。

#include<cstdio>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200005;
int key[maxn],dis[maxn]={0},left[maxn]={0},right[maxn]={0},dl[maxn];
int i,j,k,l,r,t,n,m,tot,root;
int merge(int a,int b){
    if (!a) return b;
    if (!b) return a;
    if (key[a]>key[b]) a^=b^=a^=b;
    right[a]=merge(right[a],b);
    if (dis[right[a]]>dis[left[a]]) right[a]^=left[a]^=right[a]^=left[a];
    dis[a]=dis[right[a]]+1;
    return a;
}
int deletemin(int x){
    return merge(left[x],right[x]);
}
int add(int x){
    key[++tot]=x;
    return tot;
}
int main(){
    scanf("%d",&n);
    dis[0]=-1;
    r=0;
    fo(i,1,n){
        scanf("%d",&t);
        r=r%n+1;
        dl[r]=add(t);
    }
    l=0;
    tot=0;
    while ((l%n+1)!=r){
        l=l%n+1;
        j=dl[l];
        l=l%n+1;
        k=dl[l];
        i=merge(j,k);
        r=r%n+1;
        dl[r]=i;
    }
    root=dl[r];
    fo(i,1,n){
        printf("%d\n",key[root]);
        root=deletemin(root);
    }
    return 0;
}

3、快速排序调用STL的sort用cmp(状态106442)

我们在algorithm算法库内调用sort,并且打上cmp。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int a[200005];
int i,j,k,l,t,n;
bool cmp(int a,int b){
    return a<b;
}
int main(){
    scanf("%d",&n);
    fo(i,1,n) scanf("%d",&a[i]);
    sort(a+1,a+n+1,cmp);
    fo(i,1,n) printf("%d\n",a[i]);
    return 0;
}

4、splay(状态110039)

我们可以用splay做这道题,最后中序遍历即可。每读进一个数插入其后将其旋至根进行平衡调整。

#include<cstdio>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int father[200005],tree[200005][2],key[200005],root,i,j,k,l,t,n,m,tot;
void insert(int &x,int y){
    if (!x){
        x=++tot;
        key[x]=y;
        return;
    }
    if (y<key[x]){
        insert(tree[x][0],y);
        father[tree[x][0]]=x;
    }
    else{
        insert(tree[x][1],y);
        father[tree[x][1]]=x;
    }
}
int pd(int x){
    if (x==tree[father[x]][0]) return 0;else return 1;
}
void rotate(int x){
    int y=father[x],z=pd(x);
    father[x]=father[y];
    if (father[x]) tree[father[x]][pd(y)]=x;
    tree[y][z]=tree[x][1-z];
    if (tree[x][1-z]) father[tree[x][1-z]]=y;
    father[y]=x;
    tree[x][1-z]=y;
}
void splay(int x,int y){
    while (father[x]!=y){
        if (father[father[x]]!=y)
           if (pd(x)==pd(father[x])) rotate(father[x]);else rotate(x);
        rotate(x);
    }
    if (!y) root=x;
}
int getmin(int x){
    if (!tree[x][0]) return x;
    else return getmin(tree[x][0]);
}
int merge(int a,int b){
    father[a]=0;
    father[b]=0;
    if (!a) return b;
    else if (!b) return a;
    int l=getmin(a);
    splay(l,0);
    father[b]=l;
    return l;
}
int main(){
    scanf("%d",&n);
    fo(i,1,n) {
        scanf("%d",&t);
        insert(root,t);
        splay(tot,0);
    }
    fo(i,1,n){
        j=getmin(root);
        printf("%d\n",key[j]);
        splay(j,0);
        root=merge(tree[j][0],tree[j][1]);
    }
}

5、平衡树调用STL中的multiset,迭代器扫描输出(状态109147)

我们可以调用multiset将元素放入,然后我们按照顺序用迭代器扫一遍即可。

#include<cstdio>
#include<set>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
multiset <int> s;
int i,j,k,l,t,n,a[200005];
int main(){
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&a[i]);
        s.insert(a[i]);
    }
    set<int>::iterator sbgjx;
    for (sbgjx=s.begin();sbgjx!=s.end();sbgjx++){
        printf("%d\n",*sbgjx);
    }
}

6、平衡树调用STL中的multiset边输出最小值边删除最小值(状态109108)

我们可以调用multiset,和刚刚不一样的是我们每次输出最小值,然后删除它。

#include<cstdio>
#include<set>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
multiset <int> s;
int i,j,k,l,t,n,a[200005];
int main(){
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&a[i]);
        s.insert(a[i]);
    }
    fo(i,1,n){
        printf("%d\n",*s.begin());
        s.erase(s.begin());
    }
}

7、平衡树调用STL中的multiset重载类型运算符,迭代器倒着输出(状态109187)

我们可以调用multiset,但我们定义类型并重载其运算符为大得靠前,最后迭代器倒着输出。

#include<cstdio>
#include<set>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
struct suan{
    int data;
    friend bool operator < (suan a,suan b){
        return a.data>b.data;
    }
};
multiset <suan> s;
int i,j,k,l,t,n,a[200005];
int main(){
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&a[i]);
        suan gjx;
        gjx.data=a[i];
        s.insert(gjx);
    }
    set<suan>::iterator sb;
    sb=s.end();
    sb--;
    do{
        printf("%d\n",(*sb).data);
        sb--;
    }while (sb!=s.begin());
    printf("%d\n",(*s.begin()).data);
}

8、优先队列重载运算符(状态106453)

我们可以调用优先队列,定义类型并重载运算符。

#include<cstdio>
#include<queue>
#include<functional>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
struct dong{
    int data;
};
priority_queue<dong> heap;
bool operator < (dong a,dong b){
    return a.data>b.data;
}
int i,j,k,l,t,n;
dong feizai;
int main(){
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&feizai.data);
        heap.push(feizai);
    }
    while (!heap.empty()){
        printf("%d\n",heap.top().data);
        heap.pop();
    }
}

9、左偏树pascal版(状态85236)

var
        key,dis,left,right,dl:array[0..200000] of longint;
        i,j,k,l,r,t,n,m,tot,root:longint;
function merge(a,b:longint):longint;
begin
        if a=0 then exit(b);
        if b=0 then exit(a);
        if key[a]>key[b] then
        begin
                a:=a xor b;
                b:=a xor b;
                a:=a xor b;
        end;
        right[a]:=merge(right[a],b);
        if dis[right[a]]>dis[left[a]] then
        begin
                right[a]:=right[a] xor left[a];
                left[a]:=right[a] xor left[a];
                right[a]:=right[a] xor left[a];
        end;
        dis[a]:=dis[right[a]]+1;
        exit(a);
end;
function deletemin(x:longint):longint;
begin
        exit(merge(left[x],right[x]));
end;
function add(x:longint):longint;
begin
        inc(tot);
        key[tot]:=x;
        exit(tot);
end;
begin
        readln(n);
        dis[0]:=-1;
        for i:=1 to n do
        begin
                readln(t);
                r:=r mod 200000+1;
                dl[r]:=add(t);
        end;
        while l mod 200000+1<>r do
        begin
                l:=l mod 200000+1;
                j:=dl[l];
                l:=l mod 200000+1;
                k:=dl[l];
                i:=merge(j,k);
                r:=r mod 200000+1;
                dl[r]:=i;
        end;
        root:=dl[r];
        for i:=1 to n do
        begin
                writeln(key[root]);
                root:=deletemin(root);
        end;
end.

10、splay pascal版(状态75528)

var
        key,father:array[0..2000000] of longint;
        tree:array[0..2000000,0..1] of longint;
        i,j,k,l,t,n,m,root,tot:longint;
function pd(x:longint):integer;
begin
        if x=tree[father[x],1] then exit(1) else exit(0);
end;
procedure rotate(x:longint);
var
        y,z:longint;
begin
        y:=father[x];
        z:=pd(x);
        father[x]:=father[y];
        if father[y]>0 then tree[father[y],pd(y)]:=x;
        tree[y,z]:=tree[x,1-z];
        if tree[y,z]>0 then father[tree[y,z]]:=y;
        tree[x,1-z]:=y;
        father[y]:=x;
        if father[x]=0 then root:=x;
end;
procedure inse(var x,y:longint);
begin
        if x=0 then
        begin
                inc(tot);
                x:=tot;    
                key[tot]:=y;
                exit;
        end;
        if y<key[x] then
        begin
                inse(tree[x,0],y);
                father[tree[x,0]]:=x;
        end
        else
        begin
                inse(tree[x,1],y);
                father[tree[x,1]]:=x;
        end;
end;
procedure splay(x,y:longint);
begin
        while father[x]<>y do
        begin
                if father[father[x]]<>y then
                        if pd(x)=pd(father[x]) then rotate(father[x]) else rotate(x);
                rotate(x);
        end;
        if y=0 then root:=x;
end;
procedure printf(x:longint);
begin
        if x=0 then exit;
        printf(tree[x,0]);
        writeln(key[x]);
        printf(tree[x,1]);
end;
begin
        readln(n);
        for i:=1 to n do
        begin
                readln(t);
                inse(root,t);
                splay(i,0);
        end;
        printf(root);
end.

11、优先队列(状态106465)

正常的优先队列,用栈实现倒着输出。

#include<cstdio>
#include<queue>
#include<stack>
#include<functional>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define ME CQF
using namespace std;
struct dong{
    int data;
};
priority_queue<dong> heap;
stack<dong> s;
bool operator < (dong a,dong b){
    return a.data<b.data;
}
int i,j,k,l,t,n;
dong feizai;
int main(){
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&feizai.data);
        heap.push(feizai);
    }
    while (!heap.empty()){
        s.push(heap.top());
        heap.pop();
    }
    while (!s.empty()){
        printf("%d\n",s.top().data);
        s.pop();
    }
}

12、翻版SBT pascal版(状态70730)

翻版SBT,只有两种情况。中序遍历即可。

var
        s,left,right,key:array[0..2000000] of longint;
        i,j,k,l,t,n,m,root,tot:longint;
procedure left_rotate(var x:longint);
var
        k:longint;
begin
        k:=right[x];
        right[x]:=left[k];
        left[k]:=x;
        s[k]:=s[x];
        s[x]:=s[left[x]]+s[right[x]]+1;
        x:=k;
end;
procedure right_rotate(var x:longint);
var
        k:longint;
begin
        k:=left[x];
        left[x]:=right[k];
        right[k]:=x;
        s[k]:=s[x];
        s[x]:=s[left[x]]+s[right[x]]+1;
        x:=k;
end;
procedure inse(var x,y:longint);
begin
        if x=0 then
        begin
                inc(tot);
                x:=tot;
                s[tot]:=1;
                key[tot]:=y;
                exit;
        end;
        inc(s[x]);
        if y<key[x] then
        begin
                inse(left[x],y);
                if s[right[x]]<s[left[left[x]]] then right_rotate(x);
        end
        else
        begin
                inse(right[x],y);
                if s[left[x]]<s[right[right[x]]] then left_rotate(x);
        end;
end;
procedure printf(x:longint);
begin
        if x=0 then exit;
        printf(left[x]);
        writeln(key[x]);
        printf(right[x]);
end;
begin
        readln(n);
        for i:=1 to n do
        begin
                readln(t);
                inse(root,t);
        end;
        printf(root);
end.

13、AVL CQF pascal版(状态69161)

CQF写的AVL。(我好像当时抄的标,面壁中)

{$inline on}
program CQF_AVL;
uses math;
const maxn=200000;
var key,left,right,h,b:array[0..maxn] of longint;
    tt,q,l:longint;
procedure work;
var t,k,wdc:longint;
procedure right_rotate(var x:longint);inline;
begin
   k:=left[x];
   left[x]:=right[k];
   right[k]:=x;
   //s[k]:=s[t];
   //s[t]:=s[left[t]]+s[right[t]]+1;
   h[x]:=max(h[left[x]],h[right[x]])+1;
   h[k]:=max(h[left[k]],h[right[k]])+1;
   x:=k;
end;
procedure left_rotate(var x:longint);inline;
begin
   k:=right[x];
   right[x]:=left[k];
   left[k]:=x;
   //s[k]:=s[t];
   //s[t]:=s[left[t]]+s[right[t]]+1;
   h[x]:=max(h[left[x]],h[right[x]])+1;
   h[k]:=max(h[left[k]],h[right[k]])+1;
   x:=k;
end;
procedure insert(var t,v:longint);inline;
begin
   if t=0 then begin
      inc(tt);
      t:=tt;
      key[t]:=v;
      //s[t]:=1;
      //h[t]:=0;
      //left[t]:=0;
      //right[t]:=0;
   end
   else begin
      //inc(s[t]);
      if v<key[t] then begin
         insert(left[t],v);
         h[t]:=max(h[left[t]],h[right[t]])+1;
         if h[left[t]]-h[right[t]]>1 then
            if v<key[left[t]] then
               right_rotate(t)
            else begin
               left_rotate(left[t]);
               right_rotate(t);
            end;
      end
      else begin
         insert(right[t],v);
         h[t]:=max(h[left[t]],h[right[t]])+1;
         if h[right[t]]-h[left[t]]>1 then
            if v>=key[right[t]] then
               left_rotate(t)
            else begin
               right_rotate(right[t]);
               left_rotate(t);
            end;
      end;
   end;
end;
begin
   tt:=0;
   t:=0;
   //s[0]:=0;
   h[0]:=-1;
   readln(q);
   for q:=1 to q do
   begin
         readln(wdc);
         insert(t,wdc);
   end;
   l:=t;
end;
procedure printf(x:longint);
begin
        if x=0 then exit;
        printf(left[x]);
        writeln(key[x]);
        printf(right[x]);
end;
begin
   work;
   printf(l);
end.

14、AVL CQF 全部读入再插入 pascal版(状态69153)

{$inline on}
program CQF_AVL;
uses math;
const maxn=200000;
var key,left,right,h,b:array[0..maxn] of longint;
    tt,q,l:longint;
procedure init;
begin
   readln(q);
   for q:=1 to q do
      readln(b[q]);
end;
procedure work;
var t,k:longint;
procedure right_rotate(var t:longint);inline;
begin
   k:=left[t];
   left[t]:=right[k];
   right[k]:=t;
   //s[k]:=s[t];
   //s[t]:=s[left[t]]+s[right[t]]+1;
   h[t]:=max(h[left[t]],h[right[t]])+1;
   h[k]:=max(h[left[k]],h[right[k]])+1;
   t:=k;
end;
procedure left_rotate(var t:longint);inline;
begin
   k:=right[t];
   right[t]:=left[k];
   left[k]:=t;
   //s[k]:=s[t];
   //s[t]:=s[left[t]]+s[right[t]]+1;
   h[t]:=max(h[left[t]],h[right[t]])+1;
   h[k]:=max(h[left[k]],h[right[k]])+1;
   t:=k;
end;
procedure insert(var t,v:longint);inline;
begin
   if t=0 then begin
      inc(tt);
      t:=tt;
      key[t]:=v;
      //s[t]:=1;
      //h[t]:=0;
      //left[t]:=0;
      //right[t]:=0;
   end
   else begin
      //inc(s[t]);
      if v<key[t] then begin
         insert(left[t],v);
         h[t]:=max(h[left[t]],h[right[t]])+1;
         if h[left[t]]-h[right[t]]>1 then
            if v<key[left[t]] then
               right_rotate(t)
            else begin
               left_rotate(left[t]);
               right_rotate(t);
            end;
      end
      else begin
         insert(right[t],v);
         h[t]:=max(h[left[t]],h[right[t]])+1;
         if h[right[t]]-h[left[t]]>1 then
            if v>=key[right[t]] then
               left_rotate(t)
            else begin
               right_rotate(right[t]);
               left_rotate(t);
            end;
      end;
   end;
end;
begin
   tt:=0;
   t:=0;
   //s[0]:=0;
   h[0]:=-1;
   for q:=1 to q do
         insert(t,b[q]);
   l:=t;
end;
procedure printf(x:longint);
begin
        if x=0 then exit;
        printf(left[x]);
        writeln(key[x]);
        printf(right[x]);
end;
begin
   init;
   work;
   printf(l);
end.

15、AVL CQF 含所有AVL常用操作 pascal版(状态69150)

{$inline on}
program CQF_AVL;
uses math;
const maxn=200000;
var key,s,left,right,h,b:array[0..maxn] of longint;
    tt,q,l:longint;
procedure init;
begin
   readln(q);
   for q:=1 to q do
      readln(b[q]);
end;
procedure work;
var t,k:longint;
procedure right_rotate(var t:longint);inline;
begin
   k:=left[t];
   left[t]:=right[k];
   right[k]:=t;
   s[k]:=s[t];
   s[t]:=s[left[t]]+s[right[t]]+1;
   h[t]:=max(h[left[t]],h[right[t]])+1;
   h[k]:=max(h[left[k]],h[right[k]])+1;
   t:=k;
end;
procedure left_rotate(var t:longint);inline;
begin
   k:=right[t];
   right[t]:=left[k];
   left[k]:=t;
   s[k]:=s[t];
   s[t]:=s[left[t]]+s[right[t]]+1;
   h[t]:=max(h[left[t]],h[right[t]])+1;
   h[k]:=max(h[left[k]],h[right[k]])+1;
   t:=k;
end;
procedure insert(var t,v:longint);inline;
begin
   if t=0 then begin
      inc(tt);
      t:=tt;
      key[t]:=v;
      s[t]:=1;
      h[t]:=0;
      left[t]:=0;
      right[t]:=0;
   end
   else begin
      inc(s[t]);
      if v<key[t] then begin
         insert(left[t],v);
         h[t]:=max(h[left[t]],h[right[t]])+1;
         if h[left[t]]-h[right[t]]>1 then
            if v<key[left[t]] then
               right_rotate(t)
            else begin
               left_rotate(left[t]);
               right_rotate(t);
            end;
      end
      else begin
         insert(right[t],v);
         h[t]:=max(h[left[t]],h[right[t]])+1;
         if h[right[t]]-h[left[t]]>1 then
            if v>=key[right[t]] then
               left_rotate(t)
            else begin
               right_rotate(right[t]);
               left_rotate(t);
            end;
      end;
   end;
end;
function delete(var t:longint;v:longint):longint;inline;
begin
   dec(s[t]);
   if (v=key[t])or(v<key[t])and(left[t]=0)or(v>key[t])and(right[t]=0) then begin
      delete:=key[t];
      if (left[t]=0)or(right[t]=0) then
         t:=left[t]+right[t]
      else
         key[t]:=delete(left[t],key[t]+1);
   end
   else
      if v<key[t] then
         delete:=delete(left[t],v)
      else
         delete:=delete(right[t],v);
   if t=0 then
      exit;
   h[t]:=max(h[left[t]],h[right[t]])+1;
   if h[right[t]]-h[left[t]]>1 then
      if h[right[right[t]]]>=h[left[right[t]]] then
         left_rotate(t)
      else begin
         right_rotate(right[t]);
         left_rotate(t);
      end;
   if h[left[t]]-h[right[t]]>1 then
      if h[left[left[t]]]>=h[right[left[t]]] then
         right_rotate(t)
      else begin
         left_rotate(left[t]);
         right_rotate(t);
      end;
end;
function find(var t,v:longint):boolean;inline;
begin
   if t=0 then
      exit(false);
   if v<key[t] then
      find:=find(left[t],v)
   else
      find:=(key[t]=v)or find(right[t],v);
end;
function rank(var t,v:longint):longint;inline;
begin
   if t=0 then
      exit(1);
   if v<=key[t] then
      rank:=rank(left[t],v)
   else
      rank:=s[left[t]]+1+rank(right[t],v);
end;
function select(var t:longint;k:longint):longint;inline;
begin
   if k=s[left[t]]+1 then
      exit(key[t]);
   if k<=s[left[t]] then
      select:=select(left[t],k)
   else
      select:=select(right[t],k-1-s[left[t]]);
end;
function pred(var t,v:longint):longint;inline;
begin
   if t=0 then
      exit(v);
   if v<=key[t] then
      pred:=pred(left[t],v)
   else begin
      pred:=pred(right[t],v);
      if pred=v then
         pred:=key[t];
   end;
end;
function succ(var t,v:longint):longint;inline;
begin
   if t=0 then
      exit(v);
   if key[t]<=v then
      succ:=succ(right[t],v)
   else begin
      succ:=succ(left[t],v);
      if succ=v then
         succ:=key[t];
   end;
end;
begin
   tt:=0;
   t:=0;
   s[0]:=0;
   h[0]:=-1;
   for q:=1 to q do
         insert(t,b[q]);
   l:=t;
end;
procedure printf(x:longint);
begin
        if x=0 then exit;
        printf(left[x]);
        writeln(key[x]);
        printf(right[x]);
end;
begin
   //assign(input,'bst.in');
   //assign(output,'bst.out');
   //reset(input);
   //rewrite(output);
   init;
   work;
   printf(l);
   //close(input);
   //close(output);
end.

16、翻版SBT 左旋右旋缩成一个过程 pascal版(状态75526)

var
        s,key,father:array[0..2000000] of longint;
        tree:array[0..2000000,0..1] of longint;
        i,j,k,l,t,n,m,root,tot:longint;
function pd(x:longint):integer;
begin
        if x=tree[father[x],1] then exit(1) else exit(0);
end;
procedure change(x:longint);
begin
        s[x]:=s[tree[x,0]]+s[tree[x,1]]+1;
end;
procedure rotate(x:longint);
var
        y,z:longint;
begin
        y:=father[x];
        z:=pd(x);
        father[x]:=father[y];
        if father[y]>0 then tree[father[y],pd(y)]:=x;
        tree[y,z]:=tree[x,1-z];
        if tree[y,z]>0 then father[tree[y,z]]:=y;
        tree[x,1-z]:=y;
        father[y]:=x;
        change(y);
        change(x);
        if father[x]=0 then root:=x; 
end;
procedure inse(var x,y:longint);
begin
        if x=0 then
        begin
                inc(tot);
                x:=tot;
                s[tot]:=1;
                key[tot]:=y;
                exit;
        end;
        inc(s[x]);
        if y<key[x] then
        begin
                inse(tree[x,0],y);
                father[tree[x,0]]:=x;
                if s[tree[x,1]]<s[tree[tree[x,0],0]] then rotate(tree[x,0]);
        end
        else
        begin
                inse(tree[x,1],y);
                father[tree[x,1]]:=x;
                if s[tree[x,0]]<s[tree[tree[x,1],1]] then rotate(tree[x,1]);
        end;
end;
procedure printf(x:longint);
begin
        if x=0 then exit;
        printf(tree[x,0]);
        writeln(key[x]);
        printf(tree[x,1]);
end;
begin
        readln(n);
        for i:=1 to n do
        begin
                readln(t);
                inse(root,t);
        end;
        printf(root);
end.

17、AVL pascal版(状态69197)

中序遍历即可。

uses math;
var
        key,h,left,right,a:array[0..200000] of longint;
        i,j,k,l,t,n,m,tot,wdc:longint;
procedure left_rotate(var x:longint);
var
        k:longint;
begin
        k:=right[x];
        right[x]:=left[k];
        left[k]:=x;
        h[x]:=max(h[left[x]],h[right[x]])+1;
        h[k]:=max(h[left[k]],h[right[k]])+1;
        x:=k;
end;
procedure right_rotate(var x:longint);
var
        k:longint;
begin
        k:=left[x];
        left[x]:=right[k];
        right[k]:=x;
        h[x]:=max(h[left[x]],h[right[x]])+1;
        h[k]:=max(h[left[k]],h[right[k]])+1;
        x:=k;
end;
procedure add(var x,y:longint);
begin
        if x=0 then
        begin
                inc(tot);
                x:=tot;
                key[x]:=y;
        end
        else
        begin
                if y<key[x] then
                begin
                        add(left[x],y);
                        h[x]:=max(h[left[x]],h[right[x]])+1;
                        if h[left[x]]-h[right[x]]>1 then
                                if y<key[left[x]] then
                                        right_rotate(x)
                                else
                                begin
                                        left_rotate(left[x]);
                                        right_rotate(x);
                                end;
                end
                else
                begin
                        add(right[x],y);
                        h[x]:=max(h[left[x]],h[right[x]])+1;
                        if h[left[x]]-h[right[x]]<-1 then
                                if y>=key[right[x]] then
                                        left_rotate(x)
                                else
                                begin
                                        right_rotate(right[x]);
                                        left_rotate(x);
                                end;
                end;
        end;
end;
procedure printf(x:longint);
begin
        if x=0 then exit;
        printf(left[x]);
        writeln(key[x]);
        printf(right[x]);
end;
begin
        readln(n);
        tot:=0;
        l:=0;
        h[0]:=-1;
        for i:=1 to n do
        begin
                readln(wdc);
                add(l,wdc);
        end;
        printf(l);
end.

18、Treap pascal版(状态69194)

中序遍历即可

uses math;
var
        key,s,h,left,right,a:array[0..200000] of longint;
        i,j,k,l,t,n,m,tot,wdc:longint;
procedure left_rotate(var x:longint);
var
        k:longint;
begin
        k:=right[x];
        right[x]:=left[k];
        left[k]:=x;
        h[x]:=max(h[left[x]],h[right[x]])+1;
        h[k]:=max(h[left[k]],h[right[k]])+1;
        x:=k;
end;
procedure right_rotate(var x:longint);
var
        k:longint;
begin
        k:=left[x];
        left[x]:=right[k];
        right[k]:=x;
        h[x]:=max(h[left[x]],h[right[x]])+1;
        h[k]:=max(h[left[k]],h[right[k]])+1;
        x:=k;
end;
procedure add(var x,y:longint);
begin
        if x=0 then
        begin
                inc(tot);
                x:=tot;
                key[x]:=y;
                s[x]:=random(1000000)+1;
        end
        else
        begin
                if y<key[x] then
                begin
                        add(left[x],y);
                        h[x]:=max(h[left[x]],h[right[x]])+1;
                        if s[x]<s[left[x]] then right_rotate(x);
                end
                else
                begin
                        add(right[x],y);
                        h[x]:=max(h[left[x]],h[right[x]])+1;
                        if s[x]<s[right[x]] then left_rotate(x);
                end;
        end;
end;
procedure printf(x:longint);
begin
        if x=0 then exit;
        printf(left[x]);
        writeln(key[x]);
        printf(right[x]);
end;
begin
        randomize;
        readln(n);
        tot:=0;
        l:=0;
        h[0]:=-1;
        for i:=1 to n do
        begin
                readln(wdc);
                add(l,wdc);
        end;
        printf(l);
end.

19、AVL 插入后自上而下调整法 pascal版(状态100914)

uses math;
var
        key,h,left,right,a:array[0..200000] of longint;
        i,j,k,l,t,n,m,tot,wdc:longint;
procedure left_rotate(var x:longint);
var
        k:longint;
begin
        k:=right[x];
        right[x]:=left[k];
        left[k]:=x;
        h[x]:=max(h[left[x]],h[right[x]])+1;
        h[k]:=max(h[left[k]],h[right[k]])+1;
        x:=k;
end;
procedure right_rotate(var x:longint);
var
        k:longint;
begin
        k:=left[x];
        left[x]:=right[k];
        right[k]:=x;
        h[x]:=max(h[left[x]],h[right[x]])+1;
        h[k]:=max(h[left[k]],h[right[k]])+1;
        x:=k;
end;
procedure add(var x,y:longint);
begin
        if x=0 then
        begin
                inc(tot);
                x:=tot;
                key[x]:=y;
        end
        else
        begin
                if y<key[x] then
                begin
                        add(left[x],y);
                        h[x]:=max(h[left[x]],h[right[x]])+1;
                end
                else
                begin
                        add(right[x],y);
                        h[x]:=max(h[left[x]],h[right[x]])+1;
                end;
        end;
end;
procedure change(var x:longint;y:longint);
var
        a,b,c:longint;
begin
        if (left[x]=0)and(right[x]=0) then exit;
        if left[y]=x then
        begin
                a:=left[x];
                b:=right[x];
                c:=right[y];
                if max(h[b],h[c])+1-h[a]>1 then left_rotate(x);
        end
        else
        begin
                a:=left[y];
                b:=left[x];
                c:=right[x];
                if max(h[a],h[b])+1-h[c]>1 then right_rotate(x);
        end;
        if h[left[x]]-h[right[x]]>1 then
        begin
                change(left[x],x);
                right_rotate(x);
        end
        else if h[right[x]]-h[left[x]]>1 then 
        begin
                change(right[x],x);
                left_rotate(x);
        end;
end;
procedure printf(x:longint);
begin
        if x=0 then exit;
        printf(left[x]);
        writeln(key[x]);
        printf(right[x]);
end;
begin
        readln(n);
        tot:=0;
        l:=0;
        h[0]:=-1;
        for i:=1 to n do
        begin
                readln(wdc);
                add(l,wdc);
                change(l,0);
        end;
        printf(l);
end.

20、调用STL中的vector二分查找插入排序(状态117827)

#include<cstdio>
#include<vector>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int a[200005];
int i,j,k,l,t,n,m;
vector <int> vec;
int main(){
    scanf("%d",&n);
    vector <int>::iterator gjx;
    fo(i,1,n){
        scanf("%d",&t);
        gjx=upper_bound(vec.begin(),vec.end(),t);
        vec.insert(gjx,t);
    }
    for(gjx=vec.begin();gjx!=vec.end();gjx++)
        printf("%d\n",*gjx);
}

接下来是一些超时的方法。

21、手打快排 c++(状态109122)

#include<cstdio>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int a[200005],i,j,k,l,t,n;
void qsort(int i,int j){
    int l=i,r=j,mid=a[(l+r)/2];
    do{
        while (a[i]<mid) i++;
        while (a[j]>mid) j--;
        if (i<=j){
            a[0]=a[i];
            a[i]=a[j];
            a[j]=a[0];
            i++;
            j--;
        }
    } while (i<=j);
    if (i<r) qsort(i,r);
    if (l<j) qsort(l,j);
}
int main(){
    scanf("%d",&n);
    fo(i,1,n) scanf("%d",&a[i]);
    qsort(1,n);
    fo(i,1,n) printf("%d\n",a[i]);
}

22、调用STL中的vector从大到小倒着输出(状态117828)

#include<cstdio>
#include<vector>
#include<algorithm>
#include<stack>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int a[200005];
int i,j,k,l,t,n,m;
vector <int> vec;
stack <int> s;
bool cmp(int a,int b){
    return a>b;
}
int main(){
    scanf("%d",&n);
    vector <int>::iterator gjx;
    fo(i,1,n){
        scanf("%d",&t);
        gjx=upper_bound(vec.begin(),vec.end(),t,cmp);
        vec.insert(gjx,t);
    }
    for(gjx=vec.begin();gjx!=vec.end();gjx++)
        s.push(*gjx);
    while (!s.empty()){
        printf("%d\n",s.top());
        s.pop();
    }
}

23、AVL平衡因子版指针写法pascal版(状态68587)

type dong=^node;
node=record
    t:longint;
    ph:-1..1;
    son:array[0..1] of dong;
    fa:dong;
end;
var
        i,j,k,l,t,n,m:longint;
        s:string;
        ch:char;
        p,f,g,a,b,fan,q:dong;
        bz:boolean;
procedure rotate(var o:dong;d:byte);
var
        b,c,k,e,f:dong;
        j:longint;
begin
        f:=o^.fa;
        if f<>nil then
                if o=f^.son[0] then j:=0 else j:=1;
        b:=o^.son[d];
        c:=o^.son[1-d];
        k:=c^.son[d];
        e:=c^.son[1-d];
        c^.son[d]:=o;
        c^.son[1-d]:=e;
        o^.fa:=c;
        if e<>nil then e^.fa:=c;
        o^.son[1-d]:=k;
        if k<>nil then k^.fa:=o;
        if f<>nil then c^.fa:=f;
        if f<>nil then f^.son[j]:=c;
        o:=c;
end;
procedure add(wdc:dong);
var
        l:longint;
begin
        if wdc=nil then
                exit;
        if wdc^.ph<>0 then
        begin
                a:=wdc;
        end;
        g:=wdc;
        l:=wdc^.t;
        if fan^.t<l then
        begin
                add(wdc^.son[0]);
        end
        else
        begin
                add(wdc^.son[1]);
        end;
end;
procedure dfs(wdc:dong);
begin
        if wdc=fan then exit;
        if fan^.t<wdc^.t then
        begin
                wdc^.ph:=1;
                dfs(wdc^.son[0]);
        end
        else
        begin
                wdc^.ph:=-1;
                dfs(wdc^.son[1]);
        end;
end;
{procedure find(wdc:dong);
var
        l:longint;
begin
        l:=wdc^.t;
        if l=k then
        begin
                writeln(wdc^.s);
                exit;
        end;
        if k<l then find(wdc^.son[0]) else find(wdc^.son[1]);
end;   }
procedure dg(wdc:dong);
begin
        if wdc=nil then exit;
        dg(wdc^.son[0]);
        writeln(wdc^.t);
        dg(wdc^.son[1]);
end;
begin

        readln(n);
        for i:=1 to n do
        begin
                readln(t);
                bz:=false;
                new(fan);
                fan^.ph:=0;
                fan^.t:=t;
                fan^.son[0]:=nil;
                fan^.son[1]:=nil;
                if p=nil then
                begin
                        p:=fan;
                        p^.fa:=nil;
                        continue;
                end;
                a:=p;
                g:=nil;
                add(p);
                if fan^.t<g^.t then g^.son[0]:=fan else g^.son[1]:=fan;
                fan^.fa:=g;
                if fan^.t<a^.t then
                begin
                        q:=a^.son[0];
                        b:=q;
                        j:=1;
                end
                else
                begin
                        q:=a^.son[1];
                        b:=q;
                        j:=-1;
                end;
                dfs(q);
                if a=p then bz:=true;
                if a^.ph=0 then a^.ph:=j
                else if a^.ph+j=0 then a^.ph:=0
                {else
                begin
                        if j=1 then
                        begin
                                if b^.ph=1 then rotate(a,1)
                                else
                                begin
                                        rotate(a^.son[0],0);
                                        rotate(a,1);
                                end;
                        end
                        else
                        begin
                                if b^.ph=-1 then rotate(a,0)
                                else
                                begin
                                        rotate(a^.son[1],1);
                                        rotate(a,0);
                                end;
                        end;
                end};
                if bz then p:=a;
        end;
        dg(p);
end.

接下来是一些别人的方法。

24、左旋右旋版splay(来自liujunjie,状态117364)

#include<set>
#include<queue>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;

typedef struct{int x,y;}note;
int const oo=2147483647;
int const maxn=200000;

int n,tot,lson[maxn+10],rson[maxn+10],data[maxn+10],father[maxn+10];

inline int get() {
    char ch;
    while (!isdigit(ch=getchar()));
    int v=ch-48;
    while (isdigit(ch=getchar())) v=v*10+ch-48;
    return v;
}

inline void scan(){
    n=get();
}

inline void left_rotate(int t){
    rson[father[t]]=lson[t];
    father[lson[t]]=father[t];
    int grand=father[father[t]];
    if(father[t]==lson[grand])lson[grand]=t;
    else rson[grand]=t;
    father[father[t]]=t;
    lson[t]=father[t];
    father[t]=grand;
}

inline void right_rotate(int t){
    lson[father[t]]=rson[t];
    father[rson[t]]=father[t];
    int grand=father[father[t]];
    if(father[t]==lson[grand])lson[grand]=t;
    else rson[grand]=t;
    father[father[t]]=t;
    rson[t]=father[t];
    father[t]=grand;
}

inline void splay(int x){
    while(father[x]!=0){
        if(x==lson[father[x]]){
            if(father[father[x]]==0)
                right_rotate(x);
            else if(father[x]==lson[father[father[x]]]){
                right_rotate(father[x]);
                right_rotate(x);
            }
            else{
                right_rotate(x);
                left_rotate(x);
            }
        }
        else{
            if(father[father[x]]==0)
                left_rotate(x);
            else if(father[x]==rson[father[father[x]]]){
                left_rotate(father[x]);
                left_rotate(x);
            }
            else{
                left_rotate(x);
                right_rotate(x);
            }
        }
    }
}

void inse(int t,int v){
    if(data[t]>v){
        if(lson[t]==0){
            lson[t]=++tot;
            data[tot]=v;
            father[tot]=t;
            splay(tot);
        }
        else inse(lson[t],v);
    }
    else{
        if(rson[t]==0){
            rson[t]=++tot;
            data[tot]=v;
            father[tot]=t;
            splay(tot);
        }
        else inse(rson[t],v);
    }
}

void print(int t){
    if(lson[t]!=0)print(lson[t]);
    printf("%d\n",data[t]);
    if(rson[t]!=0)print(rson[t]);
}

inline void solve(){
    data[0]=-oo;
    fo(i,1,n){
        int m=get();
        inse(0,m);
    }
    print(rson[0]);
}

int main(){
    scan();
    solve();
    return 0;
}

25、调用STL中的优先队列不倒着输出(来自wuchangkuan,状态100865)

将负数放进去,输出符号取反即可。

#include <cstdio>
#include <cstdlib>
#include <queue>
#include <iostream>
using namespace std;
int main()
{
    int a,n;
    cin>>n;
    priority_queue<int>q;
    while(n--)
    {
        scanf("%d",&a);
        q.push(-a);
    }
    while(!q.empty())
    {
        printf("%d\n",-q.top());
        q.pop();
    }
}

26、归并排序pascal版(来自wuchangkuan,状态81057)

var
        a,r:array[1..200000] of longint;
        n,i:longint;
procedure msort(s,t:longint);
var
        m,i,j,k:longint;
begin
        if s=t then exit;
        m:=(s+t)div 2;
        msort(s,m);
        msort(m+1,t);
        i:=s;
        j:=m+1;
        k:=s;
        while (i<=m) and (j<=t) do
        begin
                if a[i]<a[j] then
                begin
                        r[k]:=a[i];
                        inc(i);
                        inc(k);
                end else
                begin
                r[k]:=a[j];
                inc(j);
                inc(k);
                end;
        end;
        while i<=m do
        begin
                r[k]:=a[i];
                inc(i);
                inc(k);
        end;
        while j<=t do
        begin
                r[k]:=a[j];
                inc(j);
                inc(k);
        end;
        for i:=s to t do a[i]:=r[i];
end;
begin
        readln(n);
        for i:=1 to n do readln(a[i]);
        msort(1,n);
        for i:=1 to n do writeln(a[i]);
end.

27、堆排序(来自liuzihao,状态101076)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
int a[400010],num;
int b[400010]={0};
void up(int x)
{
     while(x>1 && a[x]<a[x/2]) {swap(a[x],a[x/2]);x/=2;}
}
void down(int x)
{
     int y;
     while(x*2<=num && a[x]>a[x*2] || x*2+1<=num && a[x]>a[x*2+1])
     {
         y=x*2;
         if(y+1<=num && a[y]>a[y+1]) y++;
         swap(a[x],a[y]);
         x=y;
     }
}
void insert(int x)
{
     num++;a[num]=x;
     up(num);
}
void del(int x)
{
     if(a[num]>a[x]) {a[x]=a[num];num--;down(x);}
     else {a[x]=a[num];num--;up(x);}
}
void build(int n)
{
     num=0;
     for(int i=1;i<=n;i++) insert(a[i]);
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    build(n);
    while(num>0)
    {
         b[++b[0]]=a[1];
         del(1);
    }
    for(int i=1;i<=b[0];i++) printf("%d\n",b[i]);
}

28、配对堆(来自wengwentao,状态117876)

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int MAXN = (1 << 18);

struct Pairing_Heap
{

    int Que[MAXN];
    int Val[MAXN],Next[MAXN],Final[MAXN],Pre[MAXN],Refer[MAXN],Apear[MAXN],Root,tot;

    void Clear()
    {
        for(int i = 1;i <= tot;i ++) Refer[Apear[i]] = 0;
        for(int i = 1;i <= tot;i ++) Final[i] = Next[i] = Pre[i] = Val[i] = 0;
        tot = 0;
        Root = 0;
    }

    int Merge(int a,int b)
    {
        if (!(a && b)) return a ? a : b;
        if (Val[a] > Val[b]) swap(a,b);
        Pre[Final[a]] = b,Next[b] = Final[a],Final[a] = b;
        return a;
    }

    void Extract(int x)
    {
        if (!x || x == Root) return;
        Next[Pre[x]] = Next[x],Pre[Next[x]] = Pre[x];
    }

    void Insert(int x,int y)
    {
        Refer[x] = tot,Apear[++ tot] = x,Val[tot] = y;
        Root = Merge(tot,Root);
    }

    void ChangeVal(int x,int y)
    {
        x = Refer[x];
        Extract(x);
        Val[x] = y;
        Root = Merge(x,Root);
    }

    void Value(int x,int y)
    {
        if (!Refer[x]) Insert(x,y); else ChangeVal(x,y);
    }

    int TopPos()
    {
        return Apear[Root];
    }

    int TopVal()
    {
        return Val[Root];
    }

    void Pop()
    {
        int fi = 0,en = 0;
        for(int i = Final[Root];i;i = Next[i]) Que[++ en] = i;
        Root = 0;
        while (fi != en)
        {
            fi = (fi + 1) & (MAXN - 1);
            if (fi == en) {Root = Que[fi];break;}
            int u = Que[fi],v = Que[(fi += 1) &= (MAXN - 1)];
            Que[(en += 1) &= (MAXN - 1)] = Merge(u,v);
        }
    }
}Heap;  

int main()
{
    int N;
    scanf("%d", &N);
    for(int v;N;N --)
    {
        scanf("%d", &v);
        Heap.Value(N,v);
    }
    while (Heap.Root) printf("%d\n", Heap.TopVal()),Heap.Pop();
    return 0;
}

29、左偏树用命名空间(来自caiziyi,状态103602)

/*
Programmer:Crazy Cloud
Tag:Left Heap
*/
#include <iostream>
#include <cstdio>
#define maxn 200005
#define fo(i,a,b) for(int i=a;i<=b;i++)

using namespace std;

int n,num[maxn];

namespace left_heap
{
    struct queue
    {
        int head,tail,q[maxn];
    };
    int tot(0),root,key[maxn]={0},t[maxn][2]={0},dis[maxn]={0};
    queue free={0},tr={0};

    int available(int x)
    {
        free.q[free.tail=free.tail%maxn+1]=x;
    }

    int use()
    {
        int x=free.q[free.head=free.head%maxn+1];
        free.q[free.head]=0;
        return x;
    }

    int initialization()
    {
        fo(i,1,n)
            available(i);
        dis[0]=-1;
    }

    int swap(int &x,int &y)
    {
        x=x^y;
        y=x^y;
        x=x^y;
    }

    int merge(int x,int y)
    {
        if (x==0)
            return y;
        if (y==0)
            return x;
        if (key[x]>key[y])
            swap(x,y);
        t[x][1]=merge(t[x][1],y);
        if (dis[t[x][0]]<dis[t[x][1]])
            swap(t[x][0],t[x][1]);
        dis[x]=dis[t[x][1]]+1;
        return x;
    }

    int del(int rt)
    {
        int x=merge(t[rt][0],t[rt][1]);
        key[rt]=t[rt][0]=t[rt][1]=0;
        dis[rt]=-1;
        available(rt);
        return x;
    }

    int getans()
    {
        int x=key[root];
        root=del(root);
        return x;
    }

    int build()
    {
        initialization();
        int x;
        fo(i,1,n)
        {
            x=tr.q[++tr.tail]=use();
            key[x]=num[i];
            t[x][0]=t[x][1]=dis[x]=0;
        }
        int y;
        fo(i,2,n)
        {
            x=tr.q[tr.head=tr.head%maxn+1];
            y=tr.q[tr.head=tr.head%maxn+1];
            tr.q[tr.tail=tr.tail%maxn+1]=merge(x,y);
        }
        root=tr.q[tr.tail];
    }
}

int main()
{
    //freopen("sort.in","r",stdin);
    //freopen("sort.out","w",stdout);
    scanf("%d",&n);
    fo(i,1,n)
        scanf("%d",&num[i]);
    using namespace left_heap;
    build();
    fo(i,1,n)
        printf("%d\n",getans());
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}

30、splay用命名空间(来自caiziyi,状态103437)

/*
Programmer:Crazy Cloud
Tag:Splay Tree
*/
#include <iostream>
#include <cstdio>
#define maxn 200005
#define fo(i,a,b) for(int i=a;i<=b;i++)

using namespace std;

int n,num;

namespace splay_tree
{
    int root={0},t[maxn][2]={0},fa[maxn],tot={0},key[maxn]={0};

    int side(int x){return t[fa[x]][0]==x?0:1;}

    int rotate(int x)
    {
        int y=fa[x],z=side(x);
        if (fa[x]=fa[y])
            t[fa[y]][side(y)]=x;
        if (t[y][z]=t[x][1-z])
            fa[t[y][z]]=y;
        t[x][1-z]=y;
        fa[y]=x;
        if (fa[x]==0)
            root=x;
    }

    int splay(int x,int y)
    {
        for (;fa[x]!=y;)
        {
            if (fa[fa[x]]!=y)
                if (side(x)==side(fa[x]))
                    rotate(fa[x]);
                else
                    rotate(x);
            rotate(x);
        }
        if (y==0)
            root=x;
    }

    int insert(int &rt,int x)
    {
        if (rt==0)
        {
            key[rt=++tot]=x;
            return 0;
        }
        if (x<key[rt])
        {
            insert(t[rt][0],x);
            fa[t[rt][0]]=rt;
        }
        else
        {
            insert(t[rt][1],x);
            fa[t[rt][1]]=rt;
        }
    }

    int travel(int rt)
    {
        if (rt==0)
            return 0;
        travel(t[rt][0]);
        printf("%d\n",key[rt]);
        travel(t[rt][1]);
    }
}

int main()
{
    //freopen("sort.in","r",stdin);
    //freopen("sort.out","w",stdout);
    scanf("%d",&n);
    using namespace splay_tree;
    fo(i,1,n)
    {
        scanf("%d",&num);
        insert(root,num);
        splay(i,0);
    }
    travel(root);
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}

31、快速排序pascal版(来自zhangjunyi,状态68053)

var
        n,i:longint;
        a:array[0..200000] of longint;
procedure qs(l,r:longint);
var i,j,m:longint;
begin
        i:=l;
        j:=r;
        m:=a[(i+j)div 2];
        repeat
                while a[i]<m do inc(i);
                while a[j]>m do dec(j);
                if i<=j then
                begin
                        a[0]:=a[i];
                        a[i]:=a[j];
                        a[j]:=a[0];
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then qs(l,j);
        if i<r then qs(i,r);
end;
begin
        readln(n);
        for i:=1 to n do readln(a[i]);
        qs(1,n);
        for i:=1 to n do writeln(a[i]);
end.

32、堆排序pascal版(来自zhangzhong,状态81796)

var
    a,b:array[1..200000] of longint;
    i,n,num:longint;
procedure up(x:longint);
var
    t:longint;
begin
    while (x>1)and(a[x]<a[x div 2]) do
    begin
        t:=a[x];
        a[x]:=a[x div 2];
        a[x div 2]:=t;
        x:=x div 2;
    end;
end;

procedure down(x:longint);
var
    t,y:longint;
begin
    while ((2*x<=num)and(a[x]>a[x*2]))or((2*x<=num+1)and(a[x]>a[x*2+1])) do
    begin
        y:=2*x;
        if (y+1<=num)and(a[y]>a[y+1]) then inc(y);
        t:=a[x];
        a[x]:=a[y];
        a[y]:=t;
        x:=y;
    end;
end;

procedure insert(x:longint);
begin
    inc(num);
    a[num]:=x;
    up(num);
end;

procedure delete(x:longint);
begin
    if a[num]>a[x]
    then begin a[x]:=a[num]; dec(num); down(x); end
    else begin a[x]:=a[num]; dec(num); up(x); end;
end;

procedure build;
var
    i:longint;
begin
    num:=0;
    for i:=1 to n do insert(a[i]);
end;


begin
   // assign(input,'dui.in'); reset(input);
   // assign(output,'dui.out'); rewrite(output);
    read(n);
    for i:=1 to n do read(a[i]);
    build;
    for i:=1 to n do
    begin
        b[i]:=a[1];
        delete(1);
    end;
    for i:=1 to n do writeln(b[i]);
    //close(input); close(output);
end.

新补充

由于懒得按照速度插入,新补充的暂时在这一板块,会通过公告提示更新。

替罪羊树(状态135963)

我总觉得我打得不是正版替罪羊树。这里设置的a为0.65。替罪羊树思路很简单,每次插入,然后查找最高的替罪羊(即左右两颗子树的size最大值比自己这颗子树的size的a倍还打),把以替罪羊为根的子树重建成一颗类完全二叉树。像线段树一样合并即可,具体见代码。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef double db;
const db fs=0.65;
const int maxn=200000+10;
int tree[maxn][2],size[maxn],a[maxn],key[maxn];
int i,j,k,l,t,n,m,tot,top,root;
void update(int x){
    size[x]=size[tree[x][0]]+size[tree[x][1]]+1;
}
void insert(int &x,int y){
    if (!x){
        key[x=++tot]=y;
        size[x]=1;
        return;
    }
    if (y<key[x]) insert(tree[x][0],y);else insert(tree[x][1],y);
    update(x);
}
void travel(int x){
    if (!x) return;
    travel(tree[x][0]);
    a[++top]=x;
    travel(tree[x][1]);
}
int build(int l,int r){
    if (l>r) return 0;
    int mid=(l+r)/2;
    tree[a[mid]][0]=build(l,mid-1);
    tree[a[mid]][1]=build(mid+1,r);
    update(a[mid]);
    return a[mid];
}
void rebuild(int &x){
    top=0;
    travel(x);
    x=build(1,top);
}
void change(int &x,int y){
    if (max(size[tree[x][0]],size[tree[x][1]])>size[x]*fs){
        rebuild(x);
        return;
    }
    if (y==key[x]) return;
    if (y<key[x]) change(tree[x][0],y);else change(tree[x][1],y);
}
void print(int x){
    if (!x) return;
    print(tree[x][0]);
    printf("%d\n",key[x]);
    print(tree[x][1]);
}
int main(){
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&t);
        insert(root,t);
        change(root,t);
    }
    print(root);
}

带有合并分裂操作的非旋转Treap

每次加入一点,在Treap中找到比它小的最大点然后查询该点rank,接着把、从该点后分裂,再将该点合并进去即可。
注意合并操作不能像左偏树那样交换顺序(因为这个我调了好久同一个数据几次结果都不一样sad)
为了鏖战表达式,fix的值不超过1000,然后使用了同优先级随机合并法。

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=200000+10,range=maxn*5;
int s[maxn],size[maxn],key[maxn],fix[maxn],tree[maxn][2];
int i,j,k,l,r,mid,t,n,m,tot,root;
void updata(int x){
    size[x]=size[tree[x][0]]+size[tree[x][1]]+1;
}
int find(int x,int y){
    int z;
    if (!x) return 0;
    else if (key[x]==y) return x;
    else if (key[x]<y){
        z=find(tree[x][1],y);
        if (!z) return x;else return z;
    }
    else{
        z=find(tree[x][0],y);
        if (z) return z;else return 0;
    }
}
int rank(int x,int y){
    if (!x) return 0;
    if (y<key[x]) return rank(tree[x][0],y);
    else return size[tree[x][0]]+1+rank(tree[x][1],y);
}
bool cmp(int x,int y){
    if (fix[x]==fix[y]) return (rand()%(size[x]+size[y])<size[x]);
    else return fix[x]<fix[y];
}
void merge(int l,int r,int &x){
    if (!l||!r) x=l+r;
    else {
        if (cmp(l,r)){
            merge(tree[l][1],r,tree[l][1]);
            x=l;
        }
        else{
            merge(l,tree[r][0],tree[r][0]);
            x=r;
        }
    }
    updata(x);
}
void split(int x,int y,int &l,int &r){
    if (!x){
        l=r=0;
    }
    else if (!y){
        l=0;
        r=x;
    }
    else{
        if (size[tree[x][0]]>=y){
            split(tree[x][0],y,l,r);
            tree[x][0]=r;
            updata(x);
            r=x;
        }
        else{
            split(tree[x][1],y-size[tree[x][0]]-1,l,r);
            tree[x][1]=l;
            updata(x);
            l=x;
        }
    }
}
void print(int x){
    if (!x) return;
    print(tree[x][0]);
    printf("%d\n",key[x]);
    print(tree[x][1]);
}
int main(){
    //freopen("data1.in","r",stdin);freopen("data.out","w",stdout);
    srand(time(0));
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&key[i]);
        fix[i]=rand()%1000;
    }
    root=1;
    fo(i,2,n){
        k=find(root,key[i]);
        if (k) k=rank(root,key[k]);
        split(root,k,l,r);
        merge(l,i,l);
        merge(l,r,root);
    }
    print(root);
}

手玩pb_ds库系列

#include<cstdio>
#include<ext/pb_ds/priority_queue.hpp>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
using namespace __gnu_pbds;
int i,j,k,l,t,n,m;
int main(){
    __gnu_pbds::priority_queue<int,greater<int>,pairing_heap_tag> heap;
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&t);
        heap.push(t);
    }
    fo(i,1,n){
        printf("%d\n",heap.top());
        heap.pop();
    }
}
#include<cstdio>
#include<ext/pb_ds/priority_queue.hpp>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
using namespace __gnu_pbds;
int i,j,k,l,t,n,m;
int main(){
    __gnu_pbds::priority_queue<int,greater<int>,binomial_heap_tag> heap;
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&t);
        heap.push(t);
    }
    fo(i,1,n){
        printf("%d\n",heap.top());
        heap.pop();
    }
}
#include<cstdio>
#include<ext/pb_ds/priority_queue.hpp>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
using namespace __gnu_pbds;
int i,j,k,l,t,n,m;
int main(){
    __gnu_pbds::priority_queue<int,greater<int>,thin_heap_tag> heap;
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&t);
        heap.push(t);
    }
    fo(i,1,n){
        printf("%d\n",heap.top());
        heap.pop();
    }
}
#include<cstdio>
#include<ext/pb_ds/priority_queue.hpp>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
using namespace __gnu_pbds;
int i,j,k,l,t,n,m;
int main(){
    __gnu_pbds::priority_queue<int,greater<int>,rc_binomial_heap_tag> heap;
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&t);
        heap.push(t);
    }
    fo(i,1,n){
        printf("%d\n",heap.top());
        heap.pop();
    }
}
#include<cstdio>
#include<ext/pb_ds/priority_queue.hpp>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
using namespace __gnu_pbds;
typedef __gnu_pbds::priority_queue<int,greater<int>,pairing_heap_tag> heap;
const int maxn=200000+10;
heap a[maxn];
int dl[maxn*2];
int i,j,k,l,t,n,m;
int main(){
    scanf("%d",&n);
    k=1;l=0;
    fo(i,1,n){
        scanf("%d",&t);
        a[i].push(t);
        dl[++l]=i;
    }
    while (k<l){
        a[dl[k]].join(a[dl[k+1]]);
        dl[++l]=dl[k];
        k+=2;
    }
    fo(i,1,n){
        printf("%d\n",a[dl[k]].top());
        a[dl[k]].pop();
    }
}
#include<cstdio>
#include<ext/pb_ds/priority_queue.hpp>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
using namespace __gnu_pbds;
typedef __gnu_pbds::priority_queue<int,greater<int>,binomial_heap_tag> heap;
const int maxn=200000+10;
heap a[maxn];
int dl[maxn*2];
int i,j,k,l,t,n,m;
int main(){
    scanf("%d",&n);
    k=1;l=0;
    fo(i,1,n){
        scanf("%d",&t);
        a[i].clear();
        a[i].push(t);
        dl[++l]=i;
    }
    while (k<l){
        a[dl[k]].join(a[dl[k+1]]);
        a[dl[k+1]].clear();
        dl[++l]=dl[k];
        k+=2;
    }
    fo(i,1,n){
        printf("%d\n",a[dl[k]].top());
        a[dl[k]].pop();
    }
}
#include<cstdio>
#include<ext/pb_ds/priority_queue.hpp>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
using namespace __gnu_pbds;
typedef __gnu_pbds::priority_queue<int,greater<int>,binary_heap_tag> heap;
const int maxn=200000+10;
heap a[maxn];
int dl[maxn*2];
int i,j,k,l,t,n,m;
int main(){
    scanf("%d",&n);
    k=1;l=0;
    fo(i,1,n){
        scanf("%d",&t);
        a[i].clear();
        a[i].push(t);
        dl[++l]=i;
    }
    while (k<l){
        a[dl[k]].join(a[dl[k+1]]);
        a[dl[k+1]].clear();
        dl[++l]=dl[k];
        k+=2;
    }
    fo(i,1,n){
        printf("%d\n",a[dl[k]].top());
        a[dl[k]].pop();
    }
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值