BZOJ3224 普通平衡树
浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html
浅谈\(fhq\)_\(treap\):https://www.cnblogs.com/AKMer/p/9981274.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3224
平衡树模板题。
时间复杂度:\(O(nlogn)\)
空间复杂度:\(O(n)\)
\(splay\)版代码如下:
#include <cstdio>
using namespace std;
const int maxn=1e5+5;
int n;
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct Splay {
int tot,root;
int fa[maxn],son[maxn][2];
int val[maxn],siz[maxn],cnt[maxn];
int newnode(int v) {
val[++tot]=v;
siz[tot]=cnt[tot]=1;
return tot;
}
int find(int v) {
int u=root;
while(val[u]!=v) {
if(val[u]>v) {if(son[u][0])u=son[u][0];else break;}
if(val[u]<v) {if(son[u][1])u=son[u][1];else break;}
}
return u;
}
inline int t(int u) {
return son[fa[u]][1]==u;
}
void updata(int p) {
siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]];
}
void rotate(int u) {
int ret=t(u),f=fa[u],s=son[u][ret^1];
son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
fa[f]=u;updata(f);updata(u);
}
void splay(int u) {
while(fa[u]) {
if(fa[fa[u]]) {
if(t(fa[u])==t(u))rotate(fa[u]);
else rotate(u);
}rotate(u);
}root=u;
}
void ins(int v) {
if(!root) {root=newnode(v);return;}
int u=find(v);
if(val[u]==v) {siz[u]++;cnt[u]++;splay(u);return;}
newnode(v);fa[tot]=u;son[u][val[u]<v]=tot;
splay(tot);
}
void del(int x) {
if(!root)return;
int u=find(x);splay(u);
if((val[u]!=x)||(--cnt[u])) {siz[u]--;return;}
if(!son[u][0]&&!son[u][1]) {root=0;return;}
if(!son[u][0]) {root=son[u][1];fa[root]=0;return;}
if(!son[u][1]) {root=son[u][0];fa[root]=0;return;}
int node=son[u][0];while(son[node][1])node=son[node][1];
fa[son[u][0]]=0;splay(node);
son[root][1]=son[u][1];fa[son[u][1]]=root;
updata(root);
}
int get_rk(int v) {
int u=find(v);splay(u);
if(val[u]>=v)return siz[son[u][0]]+1;
return siz[son[u][0]]+cnt[u]+1;
}
int get_val(int rk) {
int u=root;
while(rk) {
if(siz[son[u][0]]>=rk)u=son[u][0];
if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break;
if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1];
}
return val[u];
}
int get_pre(int v) {
int u=find(v);splay(u);
if(val[u]<v)return val[u];
int node=son[u][0];
while(son[node][1])node=son[node][1];
return val[node];
}
int get_suc(int v) {
int u=find(v);splay(u);
if(val[u]>v)return val[u];
int node=son[u][1];
while(son[node][0])node=son[node][0];
return val[node];
}
}T;
int main() {
n=read();
for(int i=1;i<=n;i++) {
int opt=read(),x=read();
if(opt==1)T.ins(x);
if(opt==2)T.del(x);
if(opt==3)printf("%d\n",T.get_rk(x));
if(opt==4)printf("%d\n",T.get_val(x));
if(opt==5)printf("%d\n",T.get_pre(x));
if(opt==6)printf("%d\n",T.get_suc(x));
}
return 0;
}
\(fhq\)_\(treap\)版代码如下:
#include <ctime>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
const int maxn=1e5+5;
int n;
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct fhq_treap {
int tot,root;
int fix[maxn],son[maxn][2];
int val[maxn],siz[maxn],cnt[maxn];
int newnode(int v) {
val[++tot]=v,fix[tot]=rand();
cnt[tot]=siz[tot]=1;return tot;
}
void updata(int p) {
siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]];
}
pii split(int u,int rk) {
if(!rk)return make_pair(0,u);
if(rk==siz[u])return make_pair(u,0);
if(siz[son[u][0]]>=rk) {
pii tmp=split(son[u][0],rk);
son[u][0]=tmp.second,updata(u);
return make_pair(tmp.first,u);
}
else {
pii tmp=split(son[u][1],rk-siz[son[u][0]]-cnt[u]);
son[u][1]=tmp.first,updata(u);
return make_pair(u,tmp.second);
}
}
int merge(int a,int b) {
if(!a||!b)return a+b;
if(fix[a]>fix[b])return son[a][1]=merge(son[a][1],b),updata(a),a;
return son[b][0]=merge(a,son[b][0]),updata(b),b;
}
int getkth(int u,int v,bool &bo,int delta) {
if(!u)return 0;int ans=0;
if(val[u]>v)ans=getkth(son[u][0],v,bo,delta);
else if(val[u]==v) {
if(delta!=-1||cnt[u]!=1)cnt[u]+=delta,siz[u]+=delta,bo=1;
return siz[son[u][0]];
}
else ans=siz[son[u][0]]+cnt[u]+getkth(son[u][1],v,bo,delta);
if(bo)siz[u]+=delta;return ans;
}
void ins(int v) {
bool bo=0;int rk=getkth(root,v,bo,1);
if(bo)return;pii tmp=split(root,rk);
root=merge(tmp.first,merge(newnode(v),tmp.second));
}
void del(int v) {
bool bo=0;int rk=getkth(root,v,bo,-1)+1;
if(bo)return;pii tmp1=split(root,rk);
pii tmp2=split(tmp1.first,rk-1);
root=merge(tmp2.first,tmp1.second);
}
int get_rk(int v) {
bool bo=0;
return getkth(root,v,bo,0)+1;
}
int get_val(int rk) {
int u=root;
while(rk) {
if(siz[son[u][0]]>=rk)u=son[u][0];
if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break;
if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1];
}
return val[u];
}
int get_pre(int v) {
int rk=get_rk(v)-1;
return get_val(rk);
}
int get_suc(int v) {
int rk=get_rk(v+1);
return get_val(rk);
}
}T;
int main() {
srand(time(0));n=read();
for(int i=1;i<=n;i++) {
int opt=read(),x=read();
if(opt==1)T.ins(x);
if(opt==2)T.del(x);
if(opt==3)printf("%d\n",T.get_rk(x));
if(opt==4)printf("%d\n",T.get_val(x));
if(opt==5)printf("%d\n",T.get_pre(x));
if(opt==6)printf("%d\n",T.get_suc(x));
}
return 0;
}