隐藏
「bzoj3324」普通平衡树 - Splay | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「bzoj3324」普通平衡树 - Splay

题目大意

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    $1$. 插入$x$数
    $2$. 删除$x$数(若有多个相同的数,因只删除一个)
    $3$. 查询$x$数的排名(若有多个相同的数,因输出最小的排名)
    $4$. 查询排名为$x$的数
    $5$. 求$x$的前驱(前驱定义为小于$x$,且最大的数)
    $6$. 求$x$的后继(后继定义为大于$x$,且最小的数)


题目分析

平衡树模板题。

Splay模板。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<climits>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;

inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}

const int maxn=200005;
struct Tree {
int child[2],father;
int key,size,cnt;
Tree() {}
Tree(int l,int r,int fa,int k,int s,int c):father(fa),key(k),size(s),cnt(c) {
child[0]=l;
child[1]=r;
}
};
struct Splay {
int size,root;
Tree tree[maxn];
#define ls(x) tree[x].child[0]
#define rs(x) tree[x].child[1]
#define fa(x) tree[x].father
#define cnt(x) tree[x].cnt
#define val(x) tree[x].key
#define size(x) tree[x].size
Splay() {
tree[++size]=Tree(0,2,0,-INT_MAX,0,0);
tree[++size]=Tree(0,0,1,INT_MAX,0,0);
root=size;
}
void clear(int index) {
tree[index]=Tree(0,0,0,0,0,0);
}
bool checkson(int index) {
return rs(fa(index))==index;
}
void push_up(int index) {
if(!index)return;
size(index)=size(ls(index))+size(rs(index))+cnt(index);
}
void rotate(int index) {
int father=fa(index),grand=fa(father),side=checkson(index);
if(grand)tree[grand].child[checkson(father)]=index;
tree[father].child[side]=tree[index].child[side^1];
fa(tree[father].child[side])=father;
fa(father)=index;
tree[index].child[side^1]=father;
fa(index)=grand;
push_up(father);
push_up(index);
}
void splay(int index,int target=0) {
for(int father; (father=fa(index))!=target; rotate(index))
if(fa(father)!=target)rotate(checkson(index)==checkson(father)?father:index);
if(target==0)root=index;
}
int insert(int v) {
int now=root,father=0;
while(now&&val(now)!=v) {
father=now;
size(father)++;
now=tree[now].child[val(now)<v];
}
if(now)cnt(now)++,size(now)++;
else {
tree[now=++size]=Tree(0,0,father,v,1,1);
if(father)tree[father].child[val(father)<v]=now;
}
splay(now);
return now;
}
void remove() {
int now=root,pre=pre_suc(0),suc=pre_suc(1);
splay(pre);
splay(suc,pre);
if(cnt(now)>1) {
cnt(now)--;
size(now)--;
} else {
clear(now);
ls(suc)=0;
}
size(pre)--;
size(suc)--;
}
void delete_index(int index) {
splay(index);
remove();
}
void delete_val(int v) {
if(rank(v)==-1)return;
remove();
}
int rank(int v) {
int now=root,ans=0;
while(now>0&&val(now)!=v) {
if(v<val(now))now=ls(now);
else {
ans+=size(ls(now))+cnt(now);
now=rs(now);
}
}
if(now<=0)return -1;
ans+=size(ls(now));
splay(now);
return ans+1;
}
int kth(int rank) {
int now=root;
while(now>=0&&rank>=0) {
if(ls(now)&&size(ls(now))>=rank)now=ls(now);
else {
int tmp=size(ls(now))+cnt(now);
if(rank<=tmp)return now;
rank-=tmp;
now=rs(now);
}
}
return -1;
}
int pre_suc(int bj) {
int now=tree[root].child[bj];
while(tree[now].child[bj^1])now=tree[now].child[bj^1];
return now;
}
int pre_suc(int v,int bj) {
if(rank(v)==-1) {
insert(v);
int pre=pre_suc(bj);
delete_index(size);
return pre;
} else return pre_suc(bj);
}
} bbt;

int n;
int main() {
n=Get_Int();
for(int i=1; i<=n; i++) {
int order=Get_Int();
if(order==1)bbt.insert(Get_Int());
if(order==2)bbt.delete_val(Get_Int());
if(order==3)printf("%d\n",bbt.rank(Get_Int()));
if(order==4)printf("%d\n",bbt.tree[bbt.kth(Get_Int())].key);
if(order==5||order==6)printf("%d\n",bbt.tree[bbt.pre_suc(Get_Int(),order-5)].key);
}
return 0;
}
姥爷们赏瓶冰阔落吧~