HDU 1890 Robotic Sort (Splaytree 区间翻转)

第一道区间翻转的Splaytree题,其实和线段树差不多的,标记一下,该down的时候down就行了,记录每个数在伸展树中的下标然后从根到节点push down下去。不过有一个小错误倒是让我调了好久,我是加了两个边界点-1的,这样子比较好处理区间,找到那个数后Splay到根,然后要标记下左边的数,如果直接root->ch[1]->mark ^= 1会把-1也翻转,而我刚开始直接翻转所以各种出错。所以还是应该要把要翻转的区间旋转到keytree也就是root->ch[1]->ch[0],最后mark下。


#include 
   
   
    
    
#include 
    
    
     
     
using namespace std;

#define lson x->ch[0]
#define rson x->ch[1]
#define ket (root->ch[1]->ch[0])

const int maxn = 100000+10;

struct NODE {
    NODE *pre, *ch[2];
    int id, sz, mark, val;

    void down() {
        if(mark) {
            swap(ch[0], ch[1]);
            if(ch[0]->pre)  ch[0]->mark ^= 1;
            if(ch[1]->pre)  ch[1]->mark ^= 1;
            mark = 0;
        }
    }

    void up() {
        sz = ch[0]->sz + ch[1]->sz + 1;
    }
};

struct PP {
    int val, id, pos;
    bool operator < (const PP &a) const {
        if(val == a.val)    return id < a.id;
        return val < a.val;
    }
}a[maxn], b[maxn];

struct Splaytree {
    int top;
    NODE node[maxn], *null, *root;

    void Rotate(NODE *x, int c) {
        NODE *y = x->pre;
        y->down(); x->down();
        y->ch[!c] = x->ch[c];
        if(x->ch[c] != null)    x->ch[c]->pre = y;
        x->pre = y->pre;
        if(y->pre != null)  y->pre->ch[y->pre->ch[1]==y] = x;
        x->ch[c] = y; y->pre = x;
        y->up();
    }

    void Splay(NODE *x, NODE *go) {
        while(x->pre != go) {
            if(x->pre->pre == go)   Rotate(x, x->pre->ch[0] == x);
            else {
                NODE *y = x->pre, *z = y->pre;
                int f = z->ch[1] == y;
                if(y->ch[f] == x)   Rotate(y, !f);
                else    Rotate(x, f);
                Rotate(x, !f);
            }
        }
        x->up();
        if(go == null)  root = x;
    }

    void RTO(int k, NODE *go) {
        NODE *x = root;
        x->down();
        while(lson->sz != k) {
            if(lson->sz > k)    x = lson;
            else{
                k -= lson->sz + 1;
                x = rson;
            }
            x->down();
        }
        Splay(x, go);
    }

    NODE *newnode(int c, NODE *f) {
        NODE *x = &node[++top];
        x->val = c;
        x->pre = f; x->id = top;
        x->sz = 1; x->mark = 0;
        lson = rson = null;
        return x;
    }

    NODE *build(int l, int r, NODE *f) {
        if(l > r)   return null;
        int mid = (l+r)/2;
        NODE *x = newnode(a[mid].val, f);
        a[mid].pos = x->id;
        lson = build(l, mid-1, x);
        rson = build(mid+1, r, x);
        x->up();
        return x;
    }

    void init(int n) {
        null = &node[0];
        null->sz = null->id = null->mark = 0;
        top = 0;
        root = newnode(-1, null);
        root->ch[1] = newnode(-1, root);
        ket = build(1, n, root->ch[1]);
        root->ch[1]->up(); root->up();
    }

    void find_path(NODE *x) {
        if(x == null)   return ;
        find_path(x->pre);
        x->down();
    }

    int deal(int pos) {
        NODE *x = &node[pos];
        find_path(x->pre);
        Splay(x, null);
        int ret = lson->sz-1;
        RTO(0, null);
        RTO(ret+1, root);
        ket->mark ^= 1;
        RTO(ret, null);
        RTO(ret+2, root);
        ket = null;
        root->ch[1]->up(); root->up();
        return ret;
    }

    void gao(int n) {
        for(int i = 1;i <= n; i++)
            printf("%d%c", i + deal(a[i].pos), i == n ? '\n' : ' ');
    }

}spt;

void solve() {
    int n;
    while(scanf("%d", &n) == 1 && n) {
        for(int i = 1;i <= n; i++) {
            scanf("%d", &a[i].val);
            a[i].id = i;
        }
        spt.init(n);
        sort(a+1, a+n+1);
        spt.gao(n);
    }
}

int main() {
    solve();
    return 0;
}

    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值