BZOJ3224 普通平衡树 with FHQ Treap

学了FHQTreap来试试模板,发现就这道题我的代码而言,比Treap和Scp慢,比Splay快。 当然一年过去了代码风格也有变化,等有空把各种平衡树的性能测试一番。

Code

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
//Code by Lucida
#include<bits/stdc++.h>
#define red(x) scanf("%d",&x)
//#define debug(x) std::cout<<#x<<'='<<x<<std::endl
template <class T> inline bool chkmx(T &a,const T &b){return a<b?a=b,1:0;}
template <class T> inline bool chkmn(T &a,const T &b){return a>b?a=b,1:0;}
const int MAXN=100000+10,P=1e5+7,INF=0x1f1f1f1f;
using std::pair;
using std::make_pair;
struct TreapNode
{
TreapNode *son[2];
int py,v,sz;
void up(){sz=1+son[0]->sz+son[1]->sz;}
int Rank(int);
int LowCount(int);
int Kth(int);
int Pred(int);
int Succ(int);
}*null=new TreapNode,*root=null;
typedef pair<TreapNode*,TreapNode*> NodePair;
inline void InitTreap()
{
null->son[0]=null->son[1]=null;
null->py=P;null->sz=null->v=0;
}
inline TreapNode *newTreapNode(int v)
{
static TreapNode *ME=new TreapNode[MAXN],*cur;
cur=ME++;cur->v=v;cur->son[0]=cur->son[1]=null;
cur->py=rand()%P;cur->sz=1;
return cur;
}
TreapNode *Merge(TreapNode *a,TreapNode *b)
{
if(a==null) return b;
if(b==null) return a;
if(a->py<b->py)
{
a->son[1]=Merge(a->son[1],b);
a->up();
return a;
}
else//a->val>b->val
{
b->son[0]=Merge(a,b->son[0]);
b->up();
return b;
}
}
NodePair Split(TreapNode *pos,int K)
{
NodePair cur=make_pair(null,null);
if(pos==null) return cur;
if(K<=pos->son[0]->sz)
{
cur=Split(pos->son[0],K);
pos->son[0]=cur.second,pos->up();
cur.second=pos;
}
else
{
cur=Split(pos->son[1],K-pos->son[0]->sz-1);
pos->son[1]=cur.first,pos->up();
cur.first=pos;
}
return cur;
}
void Insert(int x)
{
NodePair sp=Split(root,root->LowCount(x));
root=Merge(Merge(sp.first,newTreapNode(x)),sp.second);
}
void Delete(int x)
{
NodePair sp1=Split(root,root->LowCount(x)),
sp2=Split(sp1.second,sp1.second->Rank(x));
root=Merge(sp1.first,sp2.second);
}
int TreapNode::LowCount(int v)
{
TreapNode *pos=this;
int res=0;
while(pos!=null)
{
if(pos->v<v)
{
res+=pos->son[0]->sz+1;
pos=pos->son[1];
}
else
pos=pos->son[0];
}
return res;
}
int TreapNode::Rank(int v){return LowCount(v)+1;}
int TreapNode::Kth(int K)
{
TreapNode *pos=this;
while(pos!=null)
{
if(pos->son[0]->sz+1==K) return pos->v;
else if(K<pos->son[0]->sz+1) pos=pos->son[0];
else K-=pos->son[0]->sz+1,pos=pos->son[1];
}
return INF;
}
int TreapNode::Pred(int x)
{
TreapNode *pos=this;
int res=-INF;
while(pos!=null)
{
if(pos->v<x)
{
chkmx(res,pos->v);
pos=pos->son[1];
}
else
pos=pos->son[0];
}
return res;
}
int TreapNode::Succ(int x)
{
TreapNode *pos=this;
int res=INF;
while(pos!=null)
{
if(pos->v>x)
{
chkmn(res,pos->v);
pos=pos->son[0];
}
else
pos=pos->son[1];
}
return res;
}
int main()
{
srand(0x1f1f1f1f);
InitTreap();
//freopen("input","r",stdin);
int n;red(n);int g=0;
for(int i=1;i<=n;i++)
{
int opt,x;red(opt),red(x);
switch(opt)
{
case 1:Insert(x);break;
case 2:Delete(x);break;
case 3:printf("%d\n",root->Rank(x));break;
case 4:printf("%d\n",root->Kth(x));break;
case 5:printf("%d\n",root->Pred(x));break;
case 6:printf("%d\n",root->Succ(x));break;
}
}
return 0;
}