【模板】平衡树
\(\Large\text{有旋}TREAP\):
点击查看代码
#include <bits/stdc++.h>
using namespace std;
template<int the_size>
class TREAP {
private :
struct TREE {
int lid, rid;
int val, data;
int size, cnt;
} tree[the_size];
int tot;
int ans, ROOT;
#define lid(id) tree[id].lid
#define rid(id) tree[id].rid
#define val(id) tree[id].val
#define data(id) tree[id].data
#define size(id) tree[id].size
#define cnt(id) tree[id].cnt
void pushup(int id) {
size(id) = size(lid(id))+size(rid(id))+cnt(id);
}//上传;
void newnode(int id,int v) {
size(id) = cnt(id) = 1;
val(id) = v;
data(id) = rand();
}
void zip(int &id) {
int tmp = rid(id);
rid(id) = lid(tmp);
lid(tmp) = id;
size(tmp) = size(id);
pushup(id);
id = tmp;
}
void zap(int &id) {
int tmp = lid(id);
lid(id) = rid(tmp);
rid(tmp) = id;
size(tmp) = size(id);
pushup(id);
id = tmp;
}
void conduct_insert(int &id,int v) {
if(!id) {
id = ++tot;
newnode(id,v);
return;
}
size(id)++;
if(val(id) == v) {
cnt(id)++;
} else if(val(id) < v) {
conduct_insert(rid(id),v);
if(data(rid(id)) < data(id))
zip(id);
} else {
conduct_insert(lid(id),v);
if(data(lid(id)) < data(id))
zap(id);
}
}
bool conduct_delete(int &id,int v) {
if(!id) return false;
if(val(id) == v) {
if(cnt(id) > 1) {
cnt(id)--;
size(id)--;
return true;
}
if(lid(id) == 0||rid(id) == 0) {
id = lid(id)+rid(id);
//把左或右子树上提;
return true;
} else if(data(lid(id)) < data(rid(id))) {
zap(id);
return conduct_delete(id,v);
} else {
zip(id);
return conduct_delete(id,v);
}
} else if(val(id) < v) {
bool success_key = conduct_delete(rid(id),v);
if(success_key) size(id)--;
return success_key;
} else {
bool success_key = conduct_delete(lid(id),v);
if(success_key) size(id)--;
return success_key;
}
}
int Get_Rank(int id,int v) {
if(!id) return 0;
if(val(id) == v) {
return size(lid(id))+1;
} else if(v > val(id)) {
return size(lid(id))+cnt(id)+Get_Rank(rid(id),v);
} else {
return Get_Rank(lid(id),v);
}
}
int Get_Number(int id,int k) {
if(!id) return 0;
if(k <= size(lid(id))) {
return Get_Number(lid(id),k);
} else if(k > size(lid(id))+cnt(id)) {
return Get_Number(rid(id),k-size(lid(id))-cnt(id));
} else {
return val(id);
}
}
void conduct_pre(int id,int v) {
if(!id) return;
if(val(id) < v) {
ans = id;
conduct_pre(rid(id),v);
} else {
conduct_pre(lid(id),v);
}
}
void conduct_suc(int id,int v) {
if(!id) return;
if(val(id) > v) {
ans = id;
conduct_suc(lid(id),v);
} else {
conduct_suc(rid(id),v);
}
}
#undef lid
#undef rid
#undef val
#undef data
#undef size
#undef cnt
public :
void init() {
tot = ROOT = 0;
}
void Insert(int v) {
conduct_insert(ROOT,v);
}
void Delete(int v) {
conduct_delete(ROOT,v);
}
int Rank(int v) {
return Get_Rank(ROOT,v);
}
int Number(int k) {
return Get_Number(ROOT,k);
}
int Pre(int v) {
ans = 0;
conduct_pre(ROOT,v);
return tree[ans].val;
}
int Suc(int v) {
ans = 0;
conduct_suc(ROOT,v);
return tree[ans].val;
}
};
TREAP<1000010> treap;
void work_P3369() {
treap.init();
srand('b'+'i'+'k'+'u');
int n;
scanf("%d",&n);
for(int i = 1, opt, x;i <= n;++i) {
scanf("%d %d",&opt,&x);
switch(opt) {
case 1 :
treap.Insert(x);
break;
case 2 :
treap.Delete(x);
break;
case 3 :
printf("%d\n",treap.Rank(x));
break;
case 4 :
printf("%d\n",treap.Number(x));
break;
case 5 :
printf("%d\n",treap.Pre(x));
break;
case 6 :
printf("%d\n",treap.Suc(x));
break;
}
}
}
signed main() {
work_P3369();
}
\(\Large\text{无旋}TREAP\):
点击查看代码
#include <bits/stdc++.h>
using namespace std;
enum {
the_size = 100010
};
class TREAP {
private :
struct TREE {
int lid, rid;
int value, data;
int size;
} tree[the_size];
int tot, ROOT;
#define lid(id) tree[id].lid
#define rid(id) tree[id].rid
#define val(id) tree[id].value
#define data(id) tree[id].data
#define size(id) tree[id].size
void update(int id) {
size(id) = size(lid(id))+size(rid(id))+1;
}
int new_node(int v) {
size(++tot) = 1;
val(tot) = v;
data(tot) = rand();
return tot;
}
int merge(int a,int b) {
if(!a||!b) return a+b;
if(data(a) < data(b)) {
rid(a) = merge(rid(a),b);
update(a);
return a;
} else {
lid(b) = merge(a,lid(b));
update(b);
return b;
}
}
void split(int id,int k,int &a,int &b) {
if(!id)
a = b = 0;
else {
if(val(id) <= k) {
a = id;
split(rid(id),k,rid(id),b);
} else {
b = id;
split(lid(id),k,a,lid(id));
}
update(id);
}
}
int conduct_rank(int id,int k) {
while(1) {
if(k <= size(lid(id))) {
id = lid(id);
} else if(k == size(lid(id))+1) {
return id;
} else {
k -= size(lid(id))+1;
id = rid(id);
}
}
}
public :
void Init() {
srand(time(0));
tot = ROOT = 0;
}
void Insert(int v) {
int a, b;
split(ROOT,v,a,b);
ROOT = merge(merge(a,new_node(v)),b);
}
void Delete(int v) {
int a, b, c;
split(ROOT,v,a,c);
split(a,v-1,a,b);
b = merge(lid(b),rid(b));
ROOT = merge(merge(a,b),c);
}
int Rank(int v) {
int a, b;
split(ROOT,v-1,a,b);
int ans = size(a)+1;
ROOT = merge(a,b);
return ans;
}
int Number(int k) {
return tree[conduct_rank(ROOT,k)].value;
}
int Pre(int v) {
int a, b;
split(ROOT,v-1,a,b);
int ans = tree[conduct_rank(a,size(a))].value;
ROOT = merge(a,b);
return ans;
}
int Suc(int v) {
int a, b;
split(ROOT,v,a,b);
int ans = tree[conduct_rank(b,1)].value;
ROOT = merge(a,b);
return ans;
}
} treap;
void work_P3369() {
treap.Init();
int n;
scanf("%d",&n);
for(int i = 1, opt, x;i <= n;++i) {
scanf("%d %d",&opt,&x);
switch(opt) {
case 1 :
treap.Insert(x);
break;
case 2 :
treap.Delete(x);
break;
case 3 :
printf("%d\n",treap.Rank(x));
break;
case 4 :
printf("%d\n",treap.Number(x));
break;
case 5 :
printf("%d\n",treap.Pre(x));
break;
case 6 :
printf("%d\n",treap.Suc(x));
break;
}
}
}
signed main() {
work_P3369();
}
\(\Large SPLAY\):
点击查看代码
#include <cstdio>
using namespace std;
enum {
the_size = 100010
};
class SPLAY {
private :
struct TREE {
int cid[2], pid;
int val;
int size, cnt;
} tree[the_size];
#define cid(id,which) tree[id].cid[which]
#define rid(id) tree[id].cid[1]
#define lid(id) tree[id].cid[0]
#define pid(id) tree[id].pid
#define val(id) tree[id].val
#define size(id) tree[id].size
#define cnt(id) tree[id].cnt
int tree_tot, ROOT;
void initial() {
tree_tot = ROOT = 0;
}
void pushup(int id) {
size(id) = size(cid(id,0))+size(cid(id,1))+cnt(id);
}
bool get(int id) {
return id == rid(pid(id));
//if id is pid(id)'s right son return 1;
//else return 0;
}
void clear(int id) {
lid(id) = rid(id) = pid(id) = val(id) = size(id) = cnt(id) = 0;
}
void _rorate(int id) {
int f = pid(id), g = pid(f), ch = get(id);
cid(f,ch) = cid(id,ch^1);
if(cid(id,ch^1)) pid(cid(id,ch^1)) = f;
cid(id,ch^1) = f;
pid(f) = id;
pid(id) = g;
if(g) cid(g,f == cid(g,1)) = id;
pushup(f);
pushup(id);
}
void _splay(int id) {
for(int f = pid(id);f = pid(id), f;_rorate(id))
if(pid(f)) _rorate(get(id) == get(f) ? f : id);
ROOT = id;
//把id旋转到根节点;
}
void conduct_insert(int v) {
if(!ROOT) {
val(++tree_tot) = v;
cnt(tree_tot)++;
ROOT = tree_tot;
pushup(ROOT);
return;
}
int id = ROOT, f = 0;
while(1) {
if(val(id) == v) {
cnt(id)++;
pushup(id);
pushup(f);
_splay(id);
break;
}
f = id;
id = cid(id,val(id) < v);
if(!id) {
id = ++tree_tot;
val(id) = v;
cnt(id)++;
pid(id) = f;
cid(f,val(f) < v) = id;
pushup(id);
pushup(f);
_splay(id);
break;
}
}
}
int conduct_rank(int v) {
int res = 0;
int id = ROOT;
while(1) {
if(v < val(id)) {
id = lid(id);
} else {
res += size(lid(id));
if(v == val(id)) {
_splay(id);
return res+1;
}
res += cnt(id);
id = rid(id);
}
}
}
int conduct_number(int k) {
int id = ROOT;
while(1) {
if(lid(id)&&k <= size(lid(id))) {
id = lid(id);
} else {
k -= cnt(id)+size(lid(id));
if(k <= 0) {
_splay(id);
return val(id);
}
id = cid(id,1);
}
}
}
int conduct_pre() {
int id = lid(ROOT);
if(!id) return id;
while(rid(id)) id = rid(id);
_splay(id);
return id;
}
int conduct_suc() {
int id = rid(ROOT);
if(!id) return id;
while(lid(id)) id = lid(id);
_splay(id);
return id;
}
void conduct_delete(int v) {
conduct_rank(v);
int id = ROOT;
if(cnt(id) > 1) {
cnt(id)--;
pushup(id);
return;
}
if(!lid(id)&&!rid(id)) {
clear(id);
ROOT = 0;
return;
}
if(!lid(id)) {
ROOT = rid(ROOT);
pid(ROOT) = 0;
clear(id);
return;
}
if(!rid(id)) {
ROOT = lid(ROOT);
pid(ROOT) = 0;
clear(id);
return;
}
int x = conduct_pre();
pid(rid(id)) = x;
rid(x) = rid(id);
clear(id);
pushup(ROOT);
}
#undef cid
#undef rid
#undef lid
#undef pid
#undef val
#undef size
#undef cnt
public :
void Init() {
initial();
}
void Insert(int v) {
conduct_insert(v);
}
void Delete(int v) {
conduct_delete(v);
}
int Rank(int v) {
return conduct_rank(v);
}
int Number(int k) {
return conduct_number(k);
}
int Pre(int v) {
conduct_insert(v);
int ans = conduct_pre();
conduct_delete(v);
return tree[ans].val;
}
int Suc(int v) {
conduct_insert(v);
int ans = conduct_suc();
conduct_delete(v);
return tree[ans].val;
}
} splay;
void work_P3369() {
splay.Init();
int n;
scanf("%d",&n);
for(int i = 1, opt, x;i <= n;++i) {
scanf("%d %d",&opt,&x);
switch(opt) {
case 1 :
splay.Insert(x);
break;
case 2 :
splay.Delete(x);
break;
case 3 :
printf("%d\n",splay.Rank(x));
break;
case 4 :
printf("%d\n",splay.Number(x));
break;
case 5 :
printf("%d\n",splay.Pre(x));
break;
case 6 :
printf("%d\n",splay.Suc(x));
break;
}
}
}
signed main() {
work_P3369();
}
\(\Large 01TRIE\):
点击查看代码
#include <cstdio>
using namespace std;
const int max_log = 25;
const int the_size = 1e5+10;
const int num = 10000000;
struct zero_one_TRIE {
int tot;
int sid[the_size*max_log][2];
int size[the_size*max_log];
void init() {
sid[1][0] = sid[1][1] = 0;
tot = 2;
}
int New_Node() {
sid[tot][1] = sid[tot][0] = size[tot] = 0;
return tot++;
}
void Insert(int val,int ts) {
int u = 1;
for(int i = max_log-1;i >= 0;--i) {
int v = (val>>i)&1;
if(!sid[u][v]) sid[u][v] = New_Node();
u = sid[u][v];
size[u] += ts;
}
}
int Get_Num(int k) {
int u = 1, x = 0;
for(int i = max_log-1;i >= 0;--i) {
if(size[sid[u][0]] >= k)
u = sid[u][0];
else {
x |= (1<<i);
k -= size[sid[u][0]];
u = sid[u][1];
}
}
return x;
}
int Get_Rank(int x) {
int u = 1, k = 0;
for(int i = max_log-1;i >= 0;--i) {
if((x>>i)&1) {
k += size[sid[u][0]];
u = sid[u][1];
} else u = sid[u][0];
}
return k;
}
int Get_Pre(int x) {
int w = Get_Num(Get_Rank(x));
return w;
}
int Get_Nex(int x) {
int y = Get_Num(Get_Rank(x+1)+1);
return y;
}
} trie;
int n, opt, x, ans;
signed main() {
trie.init();
scanf("%d",&n);
for(int i = 1;i <= n;++i) {
scanf("%d %d",&opt,&x);
switch(opt) {
case 1 :
trie.Insert(x+num,1);
break;
case 2 :
trie.Insert(x+num,-1);
break;
case 3 :
ans = trie.Get_Rank(x+num)+1;
printf("%d\n",ans);
break;
case 4 :
ans = trie.Get_Num(x)-num;
printf("%d\n",ans);
break;
case 5 :
ans = trie.Get_Pre(x+num)-num;
printf("%d\n",ans);
break;
case 6 :
ans = trie.Get_Nex(x+num)-num;
printf("%d\n",ans);
break;
}
}
}
\(\Large\text{朝鲜树}\):
点击查看代码
#include <cstdio>
#include <algorithm>
using namespace std;
const int Z = 1e5+10;
struct KT {
int lid, rid;
int val, size;
int cnt;
int depth;
int great;
bool operator < (const KT x) {
return val < x.val;
}
} tree[Z];
int TOT, ROOT;
#define lid(id) tree[id].lid
#define rid(id) tree[id].rid
#define val(id) tree[id].val
#define size(id) tree[id].size
#define cnt(id) tree[id].cnt
#define dep(id) tree[id].depth
#define est(id) tree[id].great
void Push_Up(int id) {
size(id) = size(lid(id))+size(rid(id))+cnt(id);
est(id) = max(est(lid(id)),est(rid(id)));
}
int Construct(int l,int r,int depth) {
if(l > r) return 0;
int mid = (l+r)>>1;
lid(mid) = Construct(l,mid-1,depth+1);
rid(mid) = Construct(mid+1,r,depth+1);
dep(mid) = depth;
Push_Up(mid);
return mid;
}
void Re_construct() {
sort(tree+1,tree+1+TOT);
ROOT = Construct(1,TOT,1);
}
void Insert(int &id,int v,int depth) {
if(id == 0) {
id = ++TOT;
size(id) = cnt(id) = 1;
val(id) = v;
dep(id) = est(id) = depth;
return;
}
if(val(id) == v) {
cnt(id)++;
size(id)++;
} else if(val(id) < v) {
Insert(rid(id),v,depth+1);
Push_Up(id);
} else {
Insert(lid(id),v,depth+1);
Push_Up(id);
}
}
int Get_Min(int &id) {
if(lid(id)) {
int res = Get_Min(lid(id));
Push_Up(id);
return res;
}
int res = id;
id = rid(id);
return res;
}
void Delete(int &id,int v) {
if(val(id) == v) {
if(cnt(id) > 1) {
cnt(id)--;
size(id)--;
return;
} else {
if(lid(id) == 0) {
id = rid(id);
return;
}
if(rid(id) == 0) {
id = lid(id);
return;
}
int gm = Get_Min(rid(id));
val(id) = val(gm);
cnt(id) = cnt(gm);
Push_Up(id);
return;
}
} else if(val(id) < v) {
Delete(rid(id),v);
Push_Up(id);
return;
} else {
Delete(lid(id),v);
Push_Up(id);
return;
}
}
int Get_Rank(int id,int k) {
if(val(id) == k)
return size(lid(id))+1;
else if(val(id) < k)
return size(lid(id))+cnt(id)+Get_Rank(rid(id),k);
else
return Get_Rank(lid(id),k);
}
int Get_Num(int id,int k) {
if(size(lid(id))+1 <= k&&size(lid(id))+cnt(id) >= k)
return val(id);
else if(size(lid(id))+1 > k)
return Get_Num(lid(id),k);
else if(size(lid(id))+cnt(id) < k)
return Get_Num(rid(id),k-size(lid(id))+cnt(id));
}
int Get_Pre(int id,int v) {
int s = id, ans;
while(s) {
if(v <= val(s))
s = lid(s);
else {
ans = s;
s = rid(s);
}
}
return val(ans);
}
int Get_Suc(int id,int v) {
int s = id, ans;
while(s) {
if(v >= val(s))
s = rid(s);
else {
ans = s;
s = lid(s);
}
}
return val(ans);
}
int n, opt, x;
signed main() {
scanf("%d",&n);
for(int outs = 1;outs <= n;++outs) {
scanf("%d %d",&opt,&x);
switch(opt) {
case 1 :
Insert(ROOT,x,1);
break;
case 2 :
Delete(ROOT,x);
break;
case 3 :
printf("%d\n",Get_Rank(ROOT,x));
break;
case 4 :
printf("%d\n",Get_Num(ROOT,x));
break;
case 5 :
printf("%d\n",Get_Pre(ROOT,x));
break;
case 6 :
printf("%d\n",Get_Suc(ROOT,x));
break;
}
if(est(ROOT) > 100) Re_construct();
}
}
\(\Large\textbf{树状数组实现}\)
\(\Large vector\text{实现}\)
\(\Large\text{替罪羊树}\)
替罪羊树实现
替罪羊树就是,啊,一旦不平衡了就重建
如何判断平不平衡呢,靠一个平衡因子\(\alpha\)
在如下代码里,\(\alpha\)设为了\(0.8\)
设节点大小(节点数)为\(size_i\),数字大小(数字个数)为\(csize_i\),未删除节点大小(未被完全删除节点个数)为\(dsize_i\)
如果
- 这个节点没被删
- 这个节点的一个子节点的子树的\(size\)大于本节点\(size\times\alpha\) 或者 该节点\(dsize \le \alpha\times size\)
重构该节点及其子树。
点击查看代码
#include <stdio.h>
template <typename Tec>
Tec max(Tec x,Tec y) {
return x < y ? y : x;
}
enum {
the_size = 1000010
};
class SGTREE {
private :
struct SGNODE {
int lid, rid;
int key, cnt;
int size, csize, dsize;
} tree[the_size];
int ROOT, tot;
int flt[the_size];
double alpha = 0.8;
#define lid(id) tree[id].lid
#define rid(id) tree[id].rid
#define key(id) tree[id].key
#define cnt(id) tree[id].cnt
#define size(id) tree[id].size
#define csize(id) tree[id].csize
#define dsize(id) tree[id].dsize
int newnode(int v) {
tot++;
key(tot) = v;
lid(tot) = rid(tot) = 0;
cnt(tot) = size(tot) = csize(tot) = dsize(tot) = 1;
return tot;
}
void update(int id) {
size(id) = size(lid(id))+size(rid(id))+1;
csize(id) = csize(lid(id))+csize(rid(id))+cnt(id);
dsize(id) = dsize(lid(id))+dsize(rid(id))+(cnt(id) != 0);
}
bool judge(int id) {
return cnt(id) &&
(alpha*size(id) <= (double)max(size(lid(id)),size(rid(id)))
|| (double) dsize(id) <= alpha*size(id));
}
void flatten(int &ldr,int id) {
if(!id) return;
flatten(ldr,lid(id));
if(cnt(id))
flt[ldr++] = id;
flatten(ldr,rid(id));
}
int recon(int l,int r) {
int mid = (l+r)>>1;
if(l >= r) return 0;
lid(flt[mid]) = recon(l,mid);
rid(flt[mid]) = recon(mid+1,r);
update(flt[mid]);
return flt[mid];
}
void reconstruct(int &id) {
int ldr = 0;
flatten(ldr,id);
id = recon(0,ldr);
}
void conduct_insert(int &id,int v) {
if(!id) {
id = newnode(v);
} else {
if(key(id) == v) {
cnt(id)++;
} else if(key(id) < v) {
conduct_insert(rid(id),v);
} else {
conduct_insert(lid(id),v);
}
update(id);
if(judge(id))
reconstruct(id);
}
}
void conduct_delete(int &id,int v) {
if(!id)
return;
else {
if(key(id) == v) {
if(cnt(id)) cnt(id)--;
} else if (key(id) < v) {
conduct_delete(rid(id),v);
} else {
conduct_delete(lid(id),v);
}
update(id);
if(judge(id))
reconstruct(id);
}
}
int conduct_number(int &id,int k) {
if(!id)
return 0;
else if(csize(lid(id)) < k&&k <= csize(lid(id))+cnt(id))
return key(id);
else if(csize(lid(id))+cnt(id) < k)
return conduct_number(rid(id),k-csize(lid(id))-cnt(id));
else
return conduct_number(lid(id),k);
}
int conduct_UB(int &id,int v) {
if(!id)
return 1;
else if(key(id) == v&&cnt(id))
return csize(lid(id))+cnt(id)+1;
else if(v < key(id))
return conduct_UB(lid(id),v);
else
return csize(lid(id))+cnt(id)+conduct_UB(rid(id),v);
}
int conduct_LB(int &id,int v) {
//Although it's not "lower_bound" ...;
if(!id)
return 0;
else if(key(id) == v&&cnt(id))
return csize(lid(id));
else if(v < key(id))
return conduct_LB(lid(id),v);
else
return csize(lid(id))+cnt(id)+conduct_LB(rid(id),v);
}
public :
void Init() {
tot = 0, ROOT = 0;
lid(ROOT) = rid(ROOT) = 0;
size(ROOT) = cnt(ROOT) = 0;
}
void Insert(int v) {
conduct_insert(ROOT,v);
}
void Delete(int v) {
conduct_delete(ROOT,v);
}
int Number(int k) {
return conduct_number(ROOT,k);
}
int Rank(int k) {
return conduct_LB(ROOT,k)+1;
}
int Upper_Bound(int v) {
return conduct_UB(ROOT,v);
}
int aUpper_Bound(int v) {
return conduct_LB(ROOT,v);
}
int Pre(int v) {
return conduct_number(ROOT,conduct_LB(ROOT,v));
}
int Suc(int v) {
return conduct_number(ROOT,conduct_UB(ROOT,v));
}
void puttree(int id) {
if(!id)
return;
printf(" > %d %d ( %d ) ( %d )\n",id,key(id),lid(id),rid(id));
printf(" %d %d %d %d\n",size(id),csize(id),dsize(id),cnt(id));
puttree(lid(id));
puttree(rid(id));
}
void output() {
printf(" ROOT :: %d\n",ROOT);
puttree(ROOT);
}
} sgt;
void work_P3369() {
sgt.Init();
int n;
scanf("%d",&n);
for(int i = 1, opt, x;i <= n;++i) {
scanf("%d %d",&opt,&x);
switch(opt) {
case 1 :
sgt.Insert(x);
break;
case 2 :
sgt.Delete(x);
break;
case 3 :
printf("%d\n",sgt.Rank(x));
break;
case 4 :
printf("%d\n",sgt.Number(x));
break;
case 5 :
printf("%d\n",sgt.Pre(x));
break;
case 6 :
printf("%d\n",sgt.Suc(x));
break;
case 7 :
sgt.output();
break;
}
}
}
signed main() {
work_P3369();
}
\(\Large AVL\ \text{树}\)
AVL树实现
AVL树是一种高度平衡的数,要求左右孩子高度差不过1。
为此他用到了左旋,右旋,左左旋,右右旋。
在插入删除后,进行旋转,保证高度差不超过1。
当然得分类讨论。
点击查看代码
#include <algorithm>
#include <stdio.h>
enum {
the_size = 100010
};
class AVL {
private :
struct TREE {
int key, cnt;
int lid, rid;
int height, size;
} tree[the_size];
int tot, ROOT;
#define key(id) tree[id].key
#define pid(id) tree[id].pid
#define lid(id) tree[id].lid
#define rid(id) tree[id].rid
#define h(id) tree[id].height
#define cnt(id) tree[id].cnt
#define size(id) tree[id].size
#define max_height(x,y) (std :: max(h(x),h(y)))
int newnode(int v) {
key(++tot) = v;
lid(tot) = rid(tot) = 0;
h(tot) = size(tot) = cnt(tot) = 1;
return tot;
}
int update(int id) {
size(id) = size(lid(id))+size(rid(id))+cnt(id);
h(id) = max_height(lid(id),rid(id))+1;
return h(id);
}
void zig(int &id) {
int cs = rid(id);
rid(id) = lid(cs);
lid(cs) = id;
update(id);
update(cs);
id = cs;
}
void zag(int &id) {
int cs = lid(id);
lid(id) = rid(cs);
rid(cs) = id;
update(id);
update(cs);
id = cs;
}
void zigzag(int &id) {
zag(rid(id));
zig(id);
}
void zagzig(int &id) {
zig(lid(id));
zag(id);
}
void conduct_insert(int &id,int v) {
if(!id) {
id = newnode(v);
return;
}
if(key(id) == v) {
++cnt(id);
update(id);
return;
}
if(key(id) < v) {
conduct_insert(rid(id),v);
update(id);
if(h(rid(id))-h(lid(id)) >= 2) {
if(v > key(rid(id)))
zig(id);
else
zigzag(id);
}
} else {
conduct_insert(lid(id),v);
update(id);
if(h(lid(id))-h(rid(id)) >= 2) {
if(v < key(lid(id)))
zag(id);
else
zagzig(id);
}
}
update(id);
}
void conduct_delete(int &id,int v) {
if(!id) return;
if(key(id) > v) {
conduct_delete(lid(id),v);
update(id);
if(h(rid(id))-h(lid(id)) >= 2) {
if(h(rid(rid(id))) >= h(rid(lid(id))))
zig(id);
else
zigzag(id);
}
} else if(key(id) < v) {
conduct_delete(rid(id),v);
update(id);
if(h(lid(id))-h(rid(id)) >= 2) {
if(h(lid(lid(id))) >= h(lid(rid(id))))
zag(id);
else
zagzig(id);
}
} else {
if(cnt(id) > 1) {
cnt(id)--;
update(id);
return;
}
if(lid(id)&&rid(id)) {
int cur = rid(id);
while(lid(cur)) cur = lid(cur);
cnt(id) = cnt(cur);
key(id) = key(cur);
cnt(cur) = 1;
conduct_delete(rid(id),key(cur));
update(id);
if(h(lid(id))-h(rid(id)) >= 2) {
if(h(lid(lid(id))) >= h(lid(rid(id))))
zag(id);
else
zagzig(id);
}
} else {
if(lid(id)) id = lid(id);
else if(rid(id)) id = rid(id);
else id = 0;
}
}
if(id)
update(id);
return;
}
int conduct_rank(int id,int v) {
if(key(id) == v)
return size(lid(id))+1;
else if(key(id) > v)
return conduct_rank(lid(id),v);
else
return conduct_rank(rid(id),v)+size(lid(id))+cnt(id);
}
int conduct_number(int id,int k) {
if(size(lid(id)) >= k)
return conduct_number(lid(id),k);
else if(cnt(id)+size(lid(id)) >= k)
return key(id);
else
return conduct_number(rid(id),k-size(lid(id))-cnt(id));
}
int conduct_pre(int v) {
int id = ROOT;
int pres = 0;
while(id) {
if(key(id) == v) {
if(lid(id)) {
id = lid(id);
while(rid(id))
id = rid(id);
pres = id;
}
break;
}
if(key(id) < v&&(key(id) > key(pres)||key(pres) <= 0))
pres = id;
id = key(id) < v ? rid(id) : lid(id);
}
return key(pres);
}
int conduct_suc(int v) {
int id = ROOT;
int sucs = 0;
while(id) {
if(key(id) == v) {
if(rid(id)) {
id = rid(id);
while(lid(id))
id = lid(id);
sucs = id;
}
break;
}
if(key(id) > v&&(key(id) < key(sucs)||key(sucs) <= 0))
sucs = id;
id = key(id) < v ? rid(id) : lid(id);
}
return key(sucs);
}
public :
void Init() {
tot = 0, ROOT = 1;
rid(ROOT) = lid(ROOT) = 0;
}
void Insert(int value) {
if(tot == 0) {
ROOT = newnode(value);
return;
}
conduct_insert(ROOT,value);
}
void Delete(int value) {
conduct_delete(ROOT,value);
}
int Rank(int value) {
return conduct_rank(ROOT,value);
}
int Number(int position) {
return conduct_number(ROOT,position);
}
int Pre(int value) {
return conduct_pre(value);
}
int Suc(int value) {
return conduct_suc(value);
}
void output(int id) {
if(id == -1) return;
printf("%d (%d %d) %d %d\n",id,lid(id),rid(id),key(id),cnt(id));
output(lid(id));
output(rid(id));
printf("back to %d\n",id);
}
void Output() {
output(ROOT);
printf("\n");
}
} avl;
void work_P3369() {
avl.Init();
int n;
scanf("%d",&n);
for(int i = 1, opt, x;i <= n;++i) {
scanf("%d %d",&opt,&x);
switch(opt) {
case 1 :
avl.Insert(x);
break;
case 2 :
avl.Delete(x);
break;
case 3 :
printf("%d\n",avl.Rank(x));
break;
case 4 :
printf("%d\n",avl.Number(x));
break;
case 5 :
printf("%d\n",avl.Pre(x));
break;
case 6 :
printf("%d\n",avl.Suc(x));
break;
}
}
}
signed main() {
work_P3369();
}
\(\Large leafytree\)
点击查看代码
#include <stdio.h>
#include <stack>
#include <vector>
class LEAFY_TREE {
private :
struct TREE {
int lid, rid, pid;
int gr, le, size;
};
std :: vector<TREE*> tree;
std :: stack<int> RE_bin;
#define lid(id) tree[id]->lid
#define rid(id) tree[id]->rid
#define pid(id) tree[id]->pid
#define maxn(id) tree[id]->gr
#define minn(id) tree[id]->le
#define size(id) tree[id]->size
#define sid(id,choice) (choice == 1 ? rid(id) : lid(id))
double alpha = 0.29289321881345247559915563789515;
double lim = 0.5857864376269049511983112757903;
int ROOT, tot;
int newnode(int v) {
int id;
if(!tot) {
tree.push_back(new TREE);
tree.push_back(new TREE);
}
if(RE_bin.empty()) {
tree.push_back(new TREE);
id = ++tot;
} else {
id = RE_bin.top();
RE_bin.pop();
}
lid(id) = rid(id) = pid(id) = 0;
maxn(id) = minn(id) = v;
size(id) = 1;
return id;
}
void delnode(int id) {
RE_bin.push(id);
}
void update(int id) {
if(lid(id)) {
minn(id) = minn(lid(id));
maxn(id) = maxn(rid(id));
size(id) = size(lid(id))+size(rid(id));
}
}
bool isRid(int id) {
return id == rid(pid(id));
}
void rorate(int id) {
int fp = pid(id), gp = pid(fp);
int ch = isRid(id);
sid(pid(sid(id,ch^1)) = fp,ch) = sid(id,ch^1);
sid(pid(id) = gp,isRid(fp)) = id;
sid(pid(fp) = id,ch^1) = fp;
update(fp);
update(id);
if(fp == ROOT)
ROOT = id;
}
void maintain(int id) {
int ch;
if(lid(id)) {
if(size(lid(id)) < size(id)*alpha)
ch = 1;
else if(size(rid(id)) < size(id)*alpha)
ch = 0;
else
return;
if(size(sid(sid(id,ch),ch^1)) >= size(sid(id,ch))*lim)
rorate(sid(sid(id,ch),ch^1));
rorate(sid(id,ch));
}
}
void conduct_insert(int id,int v) {
if(!ROOT) {
ROOT = newnode(v);
return;
}
if(size(id) == 1) {
pid(lid(id) = newnode(v)) = id;
pid(rid(id) = newnode(maxn(id))) = id;
if(v > maxn(id))
std :: swap(lid(id),rid(id));
} else {
conduct_insert(sid(id,v > maxn(lid(id))),v);
}
update(id);
maintain(id);
}
void conduct_delete(int id,int v) {
int ch = v > maxn(lid(id)), tmp;
if(size(sid(id,ch)) == 1) {
delnode(sid(id,ch));
pid(tmp = sid(id,ch^1)) = pid(id);
sid(pid(id),isRid(id)) = tmp;
delnode(id);
if(id == ROOT)
ROOT = tmp;
id = tmp;
} else {
conduct_delete(sid(id,ch),v);
}
update(id);
maintain(id);
}
int conduct_number(int id,int k) {
if(size(id) == 1)
return id;
else if(size(lid(id)) >= k)
return conduct_number(lid(id),k);
else
return conduct_number(rid(id),k-size(lid(id)));
}
int conduct_rank(int id,int k) {
if(k <= minn(id))
return 0;
else if(size(id) == 1)
return 1;
else if(maxn(lid(id)) >= k)
return conduct_rank(lid(id),k);
else
return size(lid(id))+conduct_rank(rid(id),k);
}
int conduct_pre(int id,int v) {
if(size(id) == 1) {
return id;
}
else if(minn(rid(id)) >= v)
return conduct_pre(lid(id),v);
else
return conduct_pre(rid(id),v);
}
int conduct_suc(int id,int v) {
if(size(id) == 1) {
return id;
}
else if(maxn(lid(id)) > v)
return conduct_suc(lid(id),v);
else
return conduct_suc(rid(id),v);
}
#undef lid
#undef rid
#undef pid
#undef sid
#undef maxn
#undef minn
#undef size
public :
void Insert(int v) {
conduct_insert(ROOT,v);
}
void Delete(int v) {
conduct_delete(ROOT,v);
}
int Rank(int k) {
return conduct_rank(ROOT,k)+1;
}
int Number(int k) {
return tree[conduct_number(ROOT,k)]->gr;
}
int Pre(int v) {
return tree[conduct_pre(ROOT,v)]->gr;
}
int Suc(int v) {
return tree[conduct_suc(ROOT,v)]->gr;
}
} leafy;
void work_P3369() {
int n;
scanf("%d",&n);
for(int i = 1, opt, x;i <= n;++i) {
scanf("%d %d",&opt,&x);
switch(opt) {
case 1 :
leafy.Insert(x);
break;
case 2 :
leafy.Delete(x);
break;
case 3 :
printf("%d\n",leafy.Rank(x));
break;
case 4 :
printf("%d\n",leafy.Number(x));
break;
case 5 :
printf("%d\n",leafy.Pre(x));
break;
case 6 :
printf("%d\n",leafy.Suc(x));
break;
}
}
}
signed main() {
//std :: clog << "This is Leafy Tree." << std :: endl;
work_P3369();
}
\(\Large B\ \text{树}\)
\(\Large Size\ Balanced\ Tree\)
一组样例
50
1 577793
1 408221
1 880861
2 408221
1 460353
1 223489
6 577713
4 2
5 889905
2 880861
1 100033
1 73956
1 22575
5 583761
6 571549
1 812645
4 3
1 643621
1 451623
6 14895
1 556691
4 1
1 225789
2 22575
1 632329
3 73956
1 316785
5 101413
4 11
5 639414
6 636353
1 272382
1 434049
2 643621
1 99617
2 577793
1 921581
1 894033
3 223489
1 767367
3 272382
1 642721
1 272033
3 632329
1 737721
1 864513
5 746457
1 877545
1 51097
1 484817
577793
460353
880861
577793
577793
100033
22575
22575
1
100033
643621
632329
643621
4
6
13
737721