P3369 模板普通平衡树
Posted shatianming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3369 模板普通平衡树相关的知识,希望对你有一定的参考价值。
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 xx 数
- 删除 xx 数(若有多个相同的数,因只删除一个)
- 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 )
- 查询排名为 xx 的数
- 求 xx 的前驱(前驱定义为小于 xx,且最大的数)
- 求 xx 的后继(后继定义为大于 xx,且最小的数)
很好的模板题
借鉴了一位在役国集选手
#include<bits/stdc++.h> #define MAXN 300005 using namespace std; struct Splay{ int num[MAXN],ch[MAXN][2],sz[MAXN],f[MAXN],cnt[MAXN],rt,tot; int get(int x){ return (x==ch[f[x]][1]); } int up(int x){ sz[x] = cnt[x]; if(ch[x][0])sz[x] = sz[x]+sz[ch[x][0]]; if(ch[x][1])sz[x] = sz[x]+sz[ch[x][1]]; return 0; } int rote(int x){ int y = f[x],z = f[y],k = get(x),p = get(y); if(y==0)return 0; if(z)ch[z][p] = x; if(ch[x][k^1])f[ch[x][k^1]] = y; ch[y][k] = ch[x][k^1]; ch[x][k^1] = y; f[x] = z; f[y] = x; up(y);up(x); return 0; } int splay(int x){ for(int y = f[x];(y = f[x]);rote(x)){ rote((get(x)==get(y))?y:x); } rt = x; return 0; } int rank(int x){ int now=rt,ans=1; while(1){ if(num[now]<=x){ ans = ans+sz[ch[now][0]]; if(num[now]==x){ splay(now); return ans; } ans = ans+cnt[now]; now = ch[now][1]; } else{ now = ch[now][0]; } } } int pre(){//前继 比她小的最大 int now = ch[rt][0]; while(ch[now][1])now = ch[now][1]; return now; } int suc(){ int now = ch[rt][1]; while(ch[now][0])now = ch[now][0]; return now; } int add(int x){ int now = rt; while(1){ if(num[now]==x){ cnt[now]++; splay(now); return 0; } int to = (num[now]<x); if(!ch[now][to]){ tot++; ch[now][to] = tot; num[tot] = x; f[tot] = now; cnt[tot] = 1; sz[tot] = 1; splay(tot); return 0; } else now = ch[now][to]; } } int kth(int x){ int now =rt; while(1){ if(sz[ch[now][0]]<x){ x = x-sz[ch[now][0]]; if(x<=cnt[now])return num[now]; x = x-cnt[now]; now = ch[now][1]; } else{ now = ch[now][0]; } } } int del(int x){ rank(x); if(cnt[rt]>=2){ cnt[rt]--; sz[rt]--; return 0; } else{ if((!ch[rt][0])&&(!ch[rt][1])){ rt = 0; return 0; } if(ch[rt][0]&&(!ch[rt][1])){ f[ch[rt][0]] = 0; rt =ch[rt][0]; return 0; } if((!ch[rt][0])&&ch[rt][1]){ f[ch[rt][1]] = 0; rt =ch[rt][1]; return 0; } else{ splay(pre()); ch[rt][1] = ch[ch[rt][1]][1]; f[ch[rt][1]] = rt; up(rt); return 0; } } } }T; int main(){ int n,a,b; cin>>n; for(int i=1;i<=n;i++){ cin>>a; if(a==1){ cin>>b; T.add(b); } else if(a==2){ cin>>b; T.del(b); } else if(a==3){ cin>>b; cout<<T.rank(b)<<endl; } else if(a==4){ cin>>b; cout<<T.kth(b)<<endl; } else if(a==5){ cin>>b; T.add(b); cout<<T.num[T.pre()]<<endl; T.del(b); } else if(a==6){ cin>>b; T.add(b); cout<<T.num[T.suc()]<<endl; T.del(b); } } }
以上是关于P3369 模板普通平衡树的主要内容,如果未能解决你的问题,请参考以下文章
替罪羊树 ------ luogu P3369 模板普通平衡树(Treap/SBT)