BZOJ 4825 [Hnoi2017]单旋

来源:互联网 发布:买卖宝软件下载 编辑:程序博客网 时间:2024/04/28 02:06

splay

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

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

#include<set>#include<cstdio>#include<algorithm>#define N 100005using 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