Splay怎么过

P3369 【模板】普通平衡树

这不是splay板子吗 - 前驱和后继可以直接按照定义在splay树上找 - 插入和删除是splay板子就不说了 - 寻找排名为$k$的点可以直接从$root$开始 如果当前点有左子树且k比左子树的大小小则向左子树寻找 否则向右寻找且$k-(sz[{lc}]+1)$ - 寻找第x的节点的排名 从root开始找 如果当前点的$key≤x$,向左儿子走 否则向右儿子走,$rk+(sz[lc]+1)$ 下面贴个我的代码 ```cpp #include<bits/stdc++.h> using namespace std; #define int long long const int N=100005,INF=0X66CCFF0712; int t,opt; class Spaly{ private: int f[N],ch[N][2],cnt[N],siz[N],sz,root; public: int key[N]; inline void clear(int x){ ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=siz[x]=0; } inline int get(int x){ return ch[f[x]][1]==x; } inline void update(int x){ if(x){ siz[x]=cnt[x]; if(ch[x][0]){ siz[x]+=siz[ch[x][0]]; } if(ch[x][1]){ siz[x]+=siz[ch[x][1]]; } } } inline void rotate(int x){ int old=f[x],oldf=f[old],which=get(x); ch[old][which]=ch[x][which^1]; f[ch[old][which]]=old; ch[x][which^1]=old; f[old]=x;f[x]=oldf; if(oldf) ch[oldf][ch[oldf][1]==old]=x; update(old); update(x); return; } inline void splay(int x){ for(int fa;fa=f[x];rotate(x)) if(f[fa]) rotate(get(x)==get(fa)? fa : x); root=x; } inline void insert(int v){ if(root==0){ ++sz; root=sz; ch[root][0]=ch[root][1]=f[root]=0; key[root]=v; cnt[root]=siz[root]=1; return; } int cur=root,fa=0; while(1){ if(key[cur]==v){ ++cnt[cur]; update(cur); update(fa); splay(cur); break; } fa=cur; cur=ch[cur][key[cur]<v]; if(cur==0){ ++sz; ch[sz][0]=ch[sz][1]=0; key[sz]=v; siz[sz]=1; cnt[sz]=1; f[sz]=fa; ch[fa][key[fa]<v]=sz; update(fa); splay(sz); break; } } } inline int find(int v){ int ans=0,cur=root; while(1){ if(v<key[cur]) cur=ch[cur][0]; else { ans+=(ch[cur][0] ? siz[ch[cur][0]] : 0); if(v==key[cur]){ splay(cur); return ans+1; } ans+=cnt[cur]; cur=ch[cur][1]; } } } inline int findth(int k){ int cur=root; while(1){ if(ch[cur][0] && k<=siz[ch[cur][0]]) cur=ch[cur][0]; else { int tem=(ch[cur][0] ? siz[ch[cur][0]] : 0) +cnt[cur]; if(k<=tem) return key[cur]; k-=tem; cur=ch[cur][1]; } } } inline int pre(){ int cur=ch[root][0]; while(ch[cur][1]) cur=ch[cur][1]; return cur; } inline int nxt(){ int cur=ch[root][1]; while(ch[cur][0]) cur=ch[cur][0]; return cur; } inline void del(int v){ find(v); if(cnt[root]>1){ --cnt[root]; update(root); return; } if(!ch[root][0] && !ch[root][1]){ clear(root); root=0; sz=0; return; } if(!ch[root][0]){ int oldroot=root; root=ch[root][1]; f[root]=0; clear(oldroot); --sz; return; } else if(!ch[root][1]){ int oldroot=root; root=ch[root][0]; f[root]=0; clear(oldroot); --sz; return; } int lpre=pre(),oldroot=root; splay(lpre); f[ch[oldroot][1]]=root; ch[root][1]=ch[oldroot][1]; update(root); return; } }TrEE; signed main(){ // freopen("1.in","r",stdin); cin>>t; TrEE.insert(INF); TrEE.insert(-INF); while(t--){ int x,opt; cin>>opt; if(opt==1){ cin>>x; TrEE.insert(x); } else if(opt==2){ cin>>x; TrEE.del(x); } else if(opt==3){ cin>>x; TrEE.insert(x); cout<<TrEE.find(x)-1<<endl; TrEE.del(x); } else if(opt==4){ cin>>x; cout<<TrEE.findth(x+1)<<endl; } else if(opt==5){ cin>>x; TrEE.insert(x); cout<<TrEE.key[TrEE.pre()]<<endl; TrEE.del(x); } else if(opt==6){ cin>>x; TrEE.insert(x); cout<<TrEE.key[TrEE.nxt()]<<endl; TrEE.del(x); } } } ```
by Vsinger_洛天依 @ 2024-03-07 16:47:44


|