用字典树代替平衡树,一个神奇的操作
最近在学平衡树(Splay),想过一道模版题,但是我太弱了,老是写炸,于是想了一种方法代替平衡树,代码长度也十分优秀。
好了,不BB了,让我来讲一下我想出来的方法吧。
首先,我们分析一下Splay吧,思路比较简单,主要是rotate有点难理解其他都和BST差不多,但是代码实现起来有点麻烦,细节也比较多。
对于这道模版题,我的思路是把插入的数都补位,补到10位数(其实只用补到8位),然后把它当作字符串一样插入字典树中,这样就可以保证树的高度是10,不会退化,然后就很爽了♂。
对了,还有要处理负数,这里我就直接用了一个很暴力的方法,加了个偏移量。
详情可以参照我的代码(好像代码风格有点丑):
#include<bits/stdc++.h>
using namespace std;
const int N = 1000005;
const int PY = 10000000;
int ch[N][10],gs,cnt[N],n,size[N];
void insert(string x){
int p=0;
for(int i=0;i<x.length();i++){
if(ch[p][x[i]-'0']==0) ch[p][x[i]-'0']=++gs;
p=ch[p][x[i]-'0'];
size[p]++;
}
cnt[p]++;
}
void del(string x){
int p=0;
for(int i=0;i<x.length();i++){
p=ch[p][x[i]-'0'];
size[p]--;
}
cnt[p]--;
}
int find_rank(string x){
int p=0,ret=0;
for(int i=0;i<x.length();i++){
for(int j=0;j<x[i]-'0';j++){
if(ch[p][j])ret+=size[ch[p][j]];
}
p=ch[p][x[i]-'0'];
}
return ret;
}
int find_rt(string x){
int p=0,ret=0;
for(int i=0;i<x.length();i++){
for(int j=0;j<x[i]-'0';j++){
if(ch[p][j])ret+=size[ch[p][j]];
}
p=ch[p][x[i]-'0'];
}
return cnt[p];
}
int find_x(int x){
int p=0;
string ans;
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
if(ch[p][j]){
if(size[ch[p][j]]<x) x-=size[ch[p][j]];
else {p=ch[p][j];ans=ans+char(j+'0');break;}
}
}
}
string anss="";
int o=0;
for(int i=1;i<=9;i++) if(ans[i]!='0') {o=i;break;}
for(int i=o;i<=9;i++) anss=anss+ans[i];
int s=0;
for(int i=0;i<anss.length();i++) s=s*10+anss[i]-'0';
s=s-PY;
return s;
}
string x,xx;
int c,ss;
int main(){
ios::sync_with_stdio(false);
cin>>n;
while(n--){
cin>>c;
cin>>x;
ss=0;
for(int i=0;i<x.length();i++) if(x[i]!='-')ss=ss*10+x[i]-'0';
if(x[0]=='-') ss=-ss;
ss=ss+PY;
int o=ss;
x="";
while(o){
x=char(o%10+'0')+x;
o/=10;
}
ss-=PY;
xx="";
for(int i=0;i<x.size();i++) xx=xx+x[i];
while(xx.size()<9){
xx="0"+xx;
}
xx="0"+xx;
if(c==1) insert(xx);
if(c==2) del(xx);
if(c==3) cout<<find_rank(xx)+1<<endl;
if(c==4) cout<<find_x(ss)<<endl;
if(c==5) insert(xx),cout<<find_x(find_rank(xx)+1-1)<<endl,del(xx);
if(c==6) insert(xx),cout<<find_x(find_rank(xx)+1+find_rt(xx))<<endl,del(xx);
}
return 0;
}
这一个方法感觉可拓展性不强,欢迎大家讨论(>_<)