hdu 3487 Play with Chain (Splay tree基础)

本文介绍了一种基于伸展树的数据结构实现,用于高效处理数列上的区间操作,包括区间提取、区间反转及区间剪切粘贴等。通过特定的操作如插入、选择节点和旋转等,该数据结构能灵活应对各种区间操作的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:
最基本的维护数列。
提取区间,懒惰标记。。
思路:
先推入0和n+1两个元素,以方便处理边界情况。
用到的基本操作:insert,select(选取kth,0-indexed),splay
1)提取区间[a, b]
splay a-1th 到根,splay b+1th 到根的右孩子,则 b+1th 的左子树对应该区间。
2)反转区间
先反转自己的标记,标记向下传递(访问之前)的时候,交换左右儿子指针,并反转儿子的标记
3)剪切-粘贴
先提取区间,然后 splay kth to root,then splay k+1th to right child of root,and paste the subtree to k+1th。这样就把目标区间插在了kth后面。

int n, m;

struct node {
        node *ch[2], *p;
        int key, sz, rev;
        node (int x = 0, node *c = NULL):p(0), key(x), sz(1), rev(0){ch[0] = ch[1] = c;}
        void sc( node * c, int d ) { // set child
            ch[d] = c;c->p  = this;
        }
        int which(node *x) {return ch[1] == x;}
};

class splay_tree {
private:
    void upd( node *x ) {
        x->sz = x->ch[0]->sz + x->ch[1]->sz + 1;
    }

    void rot( node *x ) {
        node *y = x->p;
        int d = y->which(x);
        y->sc(x->ch[!d], d);
        y->p->sc(x, y->p->which(y));
        x->sc(y, !d);
        upd(y);upd(x);
    }

    void splay( node *x, node *y ) {
        while ( x->p != y ) {
            if (x->p->p == y) rot(x);
            else {
                if (x->p->p->which(x->p) == x->p->which(x))
                    rot(x->p), rot(x);
                else
                    rot(x), rot(x);
            }
        }
    }

    // select kth: k is 0-based
    node* select(node* x, int k) {
        int r;
        //assert(0 <= k && k <= n+1);
        for(;;) {
            pd(x);
            r = x->ch[0]->sz;
            if (r == k) return x;
            x = x->ch[k>r];
            if (k>r) k -= r+1;
        }
        return x;
    }

    void in_order(node *x, int &cnt) {
        if (x == null) return;
        pd(x);
        in_order(x->ch[0], cnt);
        if ( 1 <= cnt && cnt <= n) {
            printf("%d", x->key);
            if (cnt == n) printf("\n");
            else printf(" ");
        }
        ++cnt;
        in_order(x->ch[1], cnt);
    }

    // push down
    void pd(node *x) {
        if (x == null) return;
        if (x->rev) {
            swap(x->ch[0], x->ch[1]);
            x->ch[0]->rev ^= 1;
            x->ch[1]->rev ^= 1;
            x->rev = 0;
        }
    }

public:
    void insert(int key) {
        node *z = root->ch[1], *p = root;
        while (z != null) {
            p = z;z = z->ch[key >= z->key];
        }
        z = new node(key, null);
        p->sc(z, key >= p->key);
        splay(z, root);
    }

    int select(int k) {
        //if (root->ch[1]->sz < k) return back();
        node * x = select(root->ch[1], k);
        return x->key;
    }

    void reverse(int l, int r) {
        node *x = select(root->ch[1], l-1),
             *y = select(root->ch[1], r+1);
        splay(x, root);
        splay(y, root->ch[1]);
        y->ch[0]->rev ^= 1;
    }

    void cut(int l, int r, int o) {
        node *x = select(root->ch[1], l-1),
             *y = select(root->ch[1], r+1);
        splay(x, root);
        splay(y, root->ch[1]);

        // cut-down subtree
        node *tmp = y->ch[0];
        y->sc(null, 0);
        upd(y);upd(x);

        x = select(root->ch[1], o),
        y = select(root->ch[1], o+1);
        splay(x, root);
        splay(y, root->ch[1]);
        // paste subtree
        y->sc(tmp, 0);
        upd(y);upd(x);
    }

    void print_inOrder() {
        int cnt = 0;
        in_order(root->ch[1], cnt);
    }

public:
    splay_tree() {
        null = new node();null->sz = 0;
        root = new node(-inf, null);
    }

    ~splay_tree() {destroy(root->ch[1]);delete root;delete null;}

    void destroy(node *x) {
        if (x == null) return;
        destroy(x->ch[0]);destroy(x->ch[1]);
        delete x;
    }
public:
    node *null;
    node *root;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值