splay
观察这种spaly的性质。插入一个点,这个点的深度就是它的前驱后继中深度较大的那个+1。单旋最小值,则最小值的右子树里的点深度不变,自己深度变为1,其他点深度+1,单旋最大值同理。删除则在这个基础上让全部深度-1。
这个是在平衡树上的子树维护,也就是一个区间维护,离线上线段树即可。然而我还是带着敬意地写了一个splay……
#include
#include
#include
#define N 100005
using namespace std;
namespace runzhe2000
{
typedef long long ll;
const int INF = 1<<29;
int m; ll ans;
struct node
{
node *ch[2], *fa;
int key, dep, mi, tag;
}mem[N], *tot, *null, *root;
void init()
{
root = null = tot = mem;
null->ch[0] = null->ch[1] = null->fa = null;
null->dep = null->mi = INF, null->tag = 0;
}
int type(node *x){return x->fa->ch[1]==x;}
node* newnode(int key, int dep){node *p = ++tot; *p = *null; p->key = key, p->dep = p->mi = dep; return p;}
void pushup(node *x){x->mi = min(x->dep, min(x->ch[0]->mi, x->ch[1]->mi));}
void pushdown(node *x)
{
if(!x->tag) return;
if(x->ch[0] != null) x->ch[0]->tag += x->tag,x->ch[0]->dep += x->tag,x->ch[0]->mi += x->tag;
if(x->ch[1] != null) x->ch[1]->tag += x->tag,x->ch[1]->dep += x->tag,x->ch[1]->mi += x->tag;
x->tag = 0;
}
void rotate(node *x)
{
node *f = x->fa; int d = type(x);
(x->fa = f->fa) != null ? x->fa->ch[type(f)] = x : 0;
(f->ch[d] = x->ch[!d]) != null ? f->ch[d]->fa = f : 0;
x->ch[!d] = f, f->fa = x, pushup(f);
}
void update(node *x){if(x==null)return;update(x->fa);pushdown(x);}
void splay(node *x)
{
update(x);
for(;x->fa!=null;)
{
if(x->fa->fa == null) rotate(x);
else if(type(x)==type(x->fa))rotate(x->fa),rotate(x);
else rotate(x),rotate(x);
}
pushup(root = x);
}
void insert(node *x, node *f, node *p, int d, node *la, node *ra)
{
if(root == null)
{
root = p;
p->dep = p->mi = 1;
return;
}
if(x == null)
{
p->fa = f, f->ch[d] = p;
p->dep = p->mi = max(la->dep==INF?0:la->dep, ra->dep==INF?0:ra->dep) + 1;
return;
}
pushdown(x); if(p->key < x->key) insert(x->ch[0], x, p, 0, la, x);
else insert(x->ch[1], x, p, 1, x, ra); pushup(x);
}
node* select(node *p, int type)
{
pushdown(p); if(type) return p->ch[1]!=null ? select(p->ch[1], 1) : p;
else return p->ch[0]!=null ? select(p->ch[0], 0) : p;
}
node* find(node *x, int d, int type) // < d
{
pushdown(x);
if(type)
{
if(x->ch[1]->mi < d) return find(x->ch[1], d, 1);
else if(x->dep < d) return x;
else return find(x->ch[0], d, 1);
}
else
{
if(x->ch[0]->mi < d) return find(x->ch[0], d, 0);
else if(x->dep < d) return x;
else return find(x->ch[1], d, 0);
}
}
void main()
{
init(); scanf("%d",&m);
for(int _ = 1, c; _ <= m; _++)
{
scanf("%d",&c);
if(c == 1)
{
int key; scanf("%d",&key); node *p = newnode(key,0);
insert(root, null, p, 0, null, null); splay(p); ans = p->dep;
}
else if(c == 2 || c == 4)
{
node *p = select(root, 0); ans = p->dep;
if(p->dep != 1)
{
node *q = find(root, p->dep, 0);
splay(q);
if(q->ch[1] != null) q->ch[1]->dep ++, q->ch[1]->mi++, q->ch[1]->tag++;
q->dep++; pushup(q);
splay(p); p->dep = 1; pushup(p);
}
if(c == 4)
{
splay(p); root = p->ch[1]; root->fa = null;
if(root != null) root->dep--, root->mi--, root->tag--;
}
}
else if(c == 3 || c == 5)
{
node *p = select(root, 1); ans = p->dep;
if(p->dep != 1)
{
node *q = find(root, p->dep, 1);
splay(q);
if(q->ch[0] != null) q->ch[0]->dep ++, q->ch[0]->mi++, q->ch[0]->tag++;
q->dep++; pushup(q);
splay(p); p->dep = 1; pushup(p);
}
if(c == 5)
{
splay(p); root = p->ch[0]; root->fa = null;
if(root != null) root->dep--, root->mi--, root->tag--;
}
}
printf("%lld\n",ans);
}
}
}
int main()
{
runzhe2000::main();
}