BZOJ 4825 [Hnoi2017]单旋

splay

观察这种spaly的性质。插入一个点,这个点的深度就是它的前驱后继中深度较大的那个+1。单旋最小值,则最小值的右子树里的点深度不变,自己深度变为1,其他点深度+1,单旋最大值同理。删除则在这个基础上让全部深度-1。

这个是在平衡树上的子树维护,也就是一个区间维护,离线上线段树即可。然而我还是带着敬意地写了一个splay……

#include<set>
#include<cstdio>
#include<algorithm>
#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();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值