您的位置:首页 > 其它

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

2015-09-03 17:24 501 查看

题目大意

给定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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: