HDU 3436 Queue-jumpers (Splaytree)

题意:有n个人,编号分别为1~n,从小到大排成一列,有q次操作。 (n <= 10^8, q <= 10^5)

Top操作:  把编号为x的人拿出来放到最前面。

Query操作: 问编号为x的人现在在第几个。

Rank操作: 问第x个人编号为多少。


思路:把Top操作和Query操作的所有数离散化下,然后把n个人分成一个个区间,比如6个人,离散化编号4, 5的人,则分成区间(1, 3) (4, 4), (5, 5), (6, 6),保存好离散化的人在伸展树节点的下标,然后把区间建成伸展树就可以了。又被一个小细节坑了好久,调了好久,就是把节点放到最前面的时候我是先把它删除,然后在插入到最前面,可是我插入到最前面的时候忘了修改它的父亲导致debug好久才发现。。每个细节都不能出错才行啊。。


#include 
   
   
    
    
#include 
    
    
     
     
using namespace std;

typedef pair
     
     
      
         pii;
#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 l, r, sz, id;

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

struct PP{
    char s[6];
    int x;
}a[maxn];

pii c[maxn<<1];
int M, b[maxn], pos[maxn];

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

    void Rotate(NODE *x, int c) {
        NODE *y = x->pre;
        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;
        while(lson->sz != k) {
            if(lson->sz > k)    x = lson;
            else {
                if(lson->sz + (x->r - x->l +1) -1 >= k)    break;
                k -= lson->sz + (x->r - x->l +1);
                x = rson;
            }
        }
        Splay(x, go);
    }

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

    void debug(NODE *x) {
        if(x != null) {
            printf("l = %d r = %d sz = %d lson = %d rson = %d\n", x->l, x->r, x->sz, lson->l, rson->l);
            debug(lson);
            debug(rson);
        }
    }

    int bin(int val) {
        int l = 0, r = M-1;
        while(l <= r) {
            int mid = (l+r)/2;
            if(b[mid] == val)   return mid;
            if(b[mid] > val)    r = mid-1;
            else    l = mid+1;
        }
        return -1;
    }

    NODE *build(int l, int r, NODE *f) {
        if(l > r)   return null;
        int mid = (l+r)/2;
        NODE *x = newnode(c[mid].first, c[mid].second, f);
        if(c[mid].first == c[mid].second) {
            int p = bin(c[mid].first);
            if(p != -1) pos[p] = 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->l = null->r = null->id = 0;
        top = 0;
        root = newnode(-1, -1, null);
        root->ch[1] = newnode(-1, -1, root);
        ket = build(0, n-1, root->ch[1]);
        root->ch[1]->up(); root->up();
    }

    int Query(int val) {
        int p = bin(val);
        NODE *x = &node[pos[p]];
        Splay(x, null);
        return root->ch[0]->sz;
    }

    int Rank(int val) {
        NODE *x = root;
        while(true) {
            if(lson->sz == val) return x->l;
            if(lson->sz > val)  x = lson;
            else {
                if(lson->sz + x->r - x->l + 1 -1 >= val)
                    return val - lson->sz + x->l;
                else {
                    val -= lson->sz + x->r - x->l + 1;
                    x = rson;
                }
            }
        }
    }

    void Top(int val) {
        int p = bin(val);
        NODE *x = &node[pos[p]];
        Splay(x, null);
        int sum = lson->sz;
        RTO(sum-1, null);
        RTO(sum + x->r - x->l + 1, root);
        x = ket; ket = null;
        root->ch[1]->up(); root->up();
        RTO(0, null);
        RTO(1, root);
        ket = x;
        x->pre = root->ch[1];
        root->ch[1]->up(); root->up();
        Splay(x, null);
    }

    void solve() {
        int n, q, t, cas = 1;
        scanf("%d", &t);
        while(t--) {
            scanf("%d%d", &n, &q);
            int tot = 0;
            for(int i = 1;i <= q; i++) {
                scanf("%s%d", a[i].s, &a[i].x);
                if(a[i].s[0] != 'R')    b[tot++] = a[i].x;
            }
            printf("Case %d:\n", cas++);
            if(tot == 0) {
                for(int i = 1;i <= q; i++)  printf("%d\n", a[i].x);
                continue;
            }
            sort(b, b + tot);
            M = 1;
            for(int i = 1;i < tot; i++) if(b[i] != b[i-1])
                b[M++] = b[i];
            tot = 0;
            if(b[0] > 1)    c[tot++] = pii(1, b[0]-1);
            for(int i = 0;i < M; i++) {
                c[tot++] = pii(b[i], b[i]);
                if(i+1 == M) {
                    if(b[i] < n)    c[tot++] = pii(b[i]+1, n);
                }
                else if(b[i]+1 < b[i+1])
                    c[tot++] = pii(b[i]+1, b[i+1]-1);
            }
            init(tot);
            for(int i = 1;i <= q; i++) {
                if(a[i].s[0] == 'T')
                    Top(a[i].x);
                else if(a[i].s[0] == 'Q')
                    printf("%d\n", Query(a[i].x));
                else
                    printf("%d\n", Rank(a[i].x));
            }
        }
    }
}spt;

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

     
     
    
    
   
   

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值