[BZOJ3506][BZOJ1552] [Cqoi2014]排序机械臂

5 篇文章 0 订阅

之前一直在调自己的delete 以为树写错了 结果居然离散化错了 坑坑坑坑坑 果然还是要多膜拜膜拜hlq大牛吗 


多保留一个信息Min 用Min来进行元素的查找定位删除等等 其他没啥了。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 100000
#define INF 99999999
int a[MAXN+10], T[MAXN+10], app[MAXN+10], A[MAXN+10], n;
struct Node {
    int key, sz, cnt, flag, Min;
    Node *ch[2], *fa;
    Node () {}
    Node(int x, int y, int z, int M) {
        key = x; sz = y; cnt = z; Min = M;
    }
    void Update() {
        sz = ch[0]->sz + ch[1]->sz + cnt;
        Min = min(key, min(ch[0]->Min, ch[1]->Min));
    }
    int cmp(int v) const {
        if(v == key) return -1;
        return v < key ? 0 : 1;
    }
}nil(0, 0, 0, INF), *NIL = &nil;
struct Splay_Tree
{
    Node *root;
    Node tree[MAXN+10];
    int ncnt;
    void init() { root = NIL; ncnt = 0 ;};
    Node *NewNode() {
        Node &t = tree[++ncnt];
        t.ch[0] = t.ch[1] = t.fa = NIL;
        t.sz = t.cnt = 1;
        t.flag = 0;
        return &tree[ncnt];
    }
    void pushdown(Node *target) {
        if(target->flag)
        {
            target->flag = 0;
            swap(target->ch[0], target->ch[1]);
            if(target->ch[0] != NIL) target->ch[0]->flag ^= 1;
            if(target->ch[1] != NIL) target->ch[1]->flag ^= 1;
        }
    }
    void Rotate(Node *x, int d)
    {
        Node *y = x->fa;
        y->ch[!d] = x->ch[d];
        if(x->ch[d] != NIL) x->ch[d]->fa = y;
        x->fa = y->fa;
        if(y->fa != NIL) y->fa->ch[y->fa->ch[1] == y] = x;
        x->ch[d] = y;
        y->fa = x;
        if(y == root) root = x;
        y->Update();
        x->Update();
    }
    void splay(Node *x, Node *target)
    {
        Node *y, *z;
        while(x->fa != target)
        {
            pushdown(x);
            y = x->fa; y->Min = y->key;
            z = y->fa; if(z != NIL) z->Min = z->key;
            if(z == target) {
                if(x == y->ch[0]) Rotate(x, 1);
                else Rotate(x, 0);
            }
            else
            {
                if(y == z->ch[0])
                    if(x == y->ch[0])
                        Rotate(y, 1), Rotate(x, 1);
                    else
                        Rotate(x, 0), Rotate(x, 1);
                else
                    if(x == y->ch[1])
                        Rotate(y, 0), Rotate(x, 0);
                    else
                        Rotate(x, 1), Rotate(x, 0);
            }
            x->Update();
        }
        pushdown(x);
    }
    int Find_rank(Node * target, int key)
    {
        pushdown(target);
        if(key == target->key) return target->ch[0]->sz + 1;
        if(key == target->ch[0]->Min) return Find_rank(target->ch[0], key);
        return target->ch[0]->sz + 1 + Find_rank(target->ch[1], key);
    }
    Node *Find_kth(Node * target, int k)
    {
        pushdown(target);
        if(k <= target->ch[0]->sz) return Find_kth(target->ch[0], k);
        if(k <= target->ch[0]->sz+1) return target;
        return Find_kth(target->ch[1], k-target->ch[0]->sz-1);
    }
    void Del(int X)
    {
        if(root == NIL) return ;
        int key = Find_rank(X);
        Node *x = Find_kth(key-1);
        splay(x, NIL);
        key = Find_rank(X);
        Node *y = Find_kth(key+1);
        splay(y, root);
        Node *target = root->ch[1]->ch[0];
        if(target->cnt > 1) {
            target->cnt--;
            target->sz--;
            splay(target, NIL);
            return ;
        }
        target->fa->ch[0] = NIL;
        root->ch[1]->Update();
        splay(root->ch[1], NIL);
    }
    void Flip(Node *target) { target->flag ^= 1; }
    void Build(Node * &target, int l, int r, Node *F)
    {
        if(r < l) return ;
        target = NewNode();
        int mid = (l + r) >> 1;
        target->Min = target->key = A[mid];
        target->fa = F;
        Build(target->ch[0], l, mid-1, target);
        Build(target->ch[1], mid+1, r, target);
        target->Update();
    }
    Node *Find_kth(int k) { return Find_kth(root, k); }
    int Find_rank(int k) { return Find_rank(root, k); }
    void Print(Node *target)
    {
        if(target == NIL) return ;
        Print(target->ch[0]);
        printf("%d ", target->key);
        Print(target->ch[1]);
    }
};
Splay_Tree sp;
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); T[i] = a[i]; }
    sort(T+1, T+1+n);
    for(int i = 1; i <= n; i++) {
        A[i+1] = lower_bound(T+1, T+1+n, a[i]) - T;
        A[i+1] += app[A[i+1]]++;
    }
    A[1] = INF; A[n+2] = INF;
    sp.Build(sp.root, 1, n+2, NIL);
    for(int i = 1; i <= n; i++)
    {
        int R = sp.Find_rank(i);
        sp.splay(sp.Find_kth(1), NIL);
        sp.splay(sp.Find_kth(R+1), sp.root);
        sp.Flip(sp.root->ch[1]->ch[0]);
        if(i!=n) printf("%d ", R-1+i-1);
        else printf("%d", R-1+i-1);
        sp.Del(i);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值