标签:操作 cpp cstring shu 平衡树 mes lin uil long
以前总是不愿意写平衡树,这次规范了一下写法.
1. 建立虚拟节点 -inf 与 inf
2. 每隔 10 次左右 splay 到根
3. 各种操作写递归版就行.
code:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <ctime>
#define ll long long
#define N 200007
#define inf 2000000000
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int val[N],n,m,root;
struct SPLAY_TREE {
#define lson s[x].ch[0]
#define rson s[x].ch[1]
struct data {
int v,si,ch[2],f;
}s[N*10];
int tot;
inline int newnode () { return ++tot; }
inline int get(int x) { return s[s[x].f].ch[1]==x; }
inline void pushup(int x) { s[x].si=s[lson].si+s[rson].si+1; }
inline void rotate(int x)
{
int old=s[x].f,fold=s[old].f,which=get(x);
s[old].ch[which]=s[x].ch[which^1];
if(s[old].ch[which])
s[s[old].ch[which]].f=old;
s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold;
if(fold)
s[fold].ch[s[fold].ch[1]==old]=x;
pushup(old),pushup(x);
}
void splay(int x,int &tar)
{
for(int u=s[tar].f,fa;(fa=s[x].f)!=u;rotate(x))
if(s[fa].f!=u)
rotate(get(fa)==get(x)?fa:x);
tar=x;
}
void build(int l,int r,int &x)
{
x=newnode();
int mid=(l+r)>>1;
s[x].v=val[mid];
if(mid>l) build(l,mid-1,lson),s[lson].f=x;
if(r>mid) build(mid+1,r,rson),s[rson].f=x;
pushup(x);
}
void ins(int &x,int fa,int v)
{
if(!x) x=newnode(),s[x].f=fa,s[x].v=v;
else ins(s[x].ch[v>s[x].v],x,v);
pushup(x);
}
int find(int x,int v)
{
if(s[x].v==v) return x;
else return find(s[x].ch[v>s[x].v],v);
}
int getpre(int x,int v)
{
if(!x) return 0;
if(s[x].v<v)
{
int a=x,b=getpre(rson,v);
return b==0?a:b;
}
else return getpre(lson,v);
}
int getaft(int x,int v)
{
if(!x) return 0;
if(s[x].v>v)
{
int a=x,b=getaft(lson,v);
return b==0?a:b;
}
else return getaft(rson,v);
}
void del(int v)
{
int x=find(root,v),l,r;
splay(x,root),l=lson,r=rson;
while(s[l].ch[1]) l=s[l].ch[1];
splay(l,s[x].ch[0]);
s[r].f=l,s[l].f=0,s[l].ch[1]=r,pushup(l),root=l;
}
int getrank(int v)
{
int x=getpre(root,v);
splay(x,root);
return s[lson].si+1;
}
int getnum(int x,int kth)
{
if(kth==s[lson].si+1) return x;
else if(kth<=s[lson].si) return getnum(lson,kth);
else return getnum(rson,kth-s[lson].si-1);
}
}bst;
int main()
{
// setIO("input");
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&val[i]);
sort(val+1,val+1+n);
val[0]=-inf,val[1+n]=inf;
bst.build(0,1+n,root);
int lastans=0,op,x,y,ans=0;
for(int i=1;i<=m;++i)
{
scanf("%d%d",&op,&x);
x^=lastans,y=0;
if(op==1) bst.ins(root,0,x),y=bst.tot;
if(op==2) bst.del(x);
if(op==3) lastans=bst.getrank(x),ans^=lastans;
if(op==4) y=bst.getnum(root,x+1),lastans=bst.s[y].v,ans^=lastans;
if(op==5) y=bst.getpre(root,x),lastans=bst.s[y].v,ans^=lastans;
if(op==6) y=bst.getaft(root,x),lastans=bst.s[y].v,ans^=lastans;
if(y&&(i%10==0)) bst.splay(y,root);
}
printf("%d\n",ans);
return 0;
}
标签:操作 cpp cstring shu 平衡树 mes lin uil long
原文地址:https://www.cnblogs.com/guangheli/p/13025969.html