pat1057 Stack

题意:在stack的操作上加一个输出当前栈中的中位数的操作。

思路:找中位数可以用splay,其它按照栈操作就好,当然也可以用二分+bit找中位数毕竟数字不大。

代码

splay

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <climits>

using namespace std;

template <class T, size_t size>
struct MemoryPool {
    T buf[size], *tail, *end;
    inline T *alloc() {
        if (top) return st[--top];
        if (tail != end) return tail++;
        return new T;
    }
    MemoryPool() : tail(buf), end(buf + size), top(0) {}
    int top;
    T *st[size];
    inline void recycle(T *x) {
        if (top > size) delete x;
        else st[top++] = x;
    }
};
 
const int MAXN = 200000;
template <class T, T INF>
struct Splay {
    enum Relation { L = 0, R = 1 };
    struct Node {
        Node *child[2], *parent, **root;
        T value;
        int size, count;
        inline void init(Node *parent, const T &value, Node **root) {
            this->parent = parent;
            this->value = value;
            this->root = root;
            this->count = this->size = 1;
            child[0] = child[1] = NULL;
        }
        inline Relation relation() {
            return this == parent->child[L] ? L : R;
        }
        inline void recycle(MemoryPool<Node, MAXN> &pool) {
            if (child[L]) pool.recycle(child[L]);
            if (child[R]) pool.recycle(child[R]);
        }
        inline void maintain() {
            size = count + (child[L] ? child[L]->size : 0) + (child[R] ? child[R]->size : 0);
        }
        inline void rotate() {
            Relation x = relation();
            Node *oldParent = parent;
            if (oldParent->parent) oldParent->parent->child[oldParent->relation()] = this;
            parent = oldParent->parent; oldParent->child[x] = child[x^1];
            if (child[x^1]) child[x^1]->parent = oldParent;
            child[x^1] = oldParent; oldParent->parent = this; oldParent->maintain(); maintain();
            if (!parent) *root = this;
        }
        inline void splay(Node *targetParent = NULL) {
            while (parent != targetParent) {
                if (parent->parent == targetParent) {
                    rotate();
                } else {
                    if (parent->relation() == relation()) parent->rotate(), rotate();
                    else rotate(), rotate();
                }
            }
        }
        inline Node *precursor() {
            splay();
            Node *v = child[L];
            while (v->child[R]) v = v->child[R];
            return v;
        }
        inline Node *successor() {
            splay();
            Node *v = child[R];
            while (v->child[L]) v = v->child[L];
            return v;
        }
        inline int rank() {return child[L] ? child[L]->size : 0;}
    } *root;
    MemoryPool<Node, MAXN> pool;
    Splay() : root(NULL) {insert(INF), insert(-INF);}
    inline Node *find(const T &value) {
        Node *v = root;
        while (v && value != v->value) {
            v = (value < v->value ? v->child[L] : v->child[R]);
        }
        return v ? (v->splay(), v) : NULL;
    }
    inline Node *insert(const T &value) {
        Node *v = find(value);
        if (v) {
            v->count++;
            v->maintain();
            return v;
        }
        Node **target = &root, *parent = NULL;
        while (*target) {
            parent = *target;
            parent->size++; 
            target = (value < parent->value ? &parent->child[L] : &parent->child[R]);
        }
        *target = pool.alloc(); (*target)->init(parent, value, &root); (*target)->splay();
        return root;
    }
    inline const T &select(int k) {
        k++;
        Node *v = root;
        while (!(v->rank() < k && v->rank() + v->count >= k)) v = (k <= v->rank() ? v->child[L] : (k -= v->rank() + v->count, v->child[R]));
        return v->splay(), v->value;
    }
    inline void erase(Node *l, Node *r) {
        Node *pre = l->precursor(), *suc = r->successor();
        pre->splay(), suc->splay(pre), suc->child[L]->recycle(pool);
        pool.recycle(suc->child[L]), suc->child[L] = NULL, suc->maintain(), pre->maintain();
    }
    inline void erase(Node *v) {
        if (v->count > 1) v->count--;
        else erase(v, v);
    }
    inline void erase(const T &l, const T &r) {
        Node *vl = find(l), *vr = find(r);
        if (!vl) vl = insert(l);
        if (!vr) vr = insert(r);
        erase(vl, vr);
    }
    inline int rank(const T &value) {
        Node *v = find(value);
        if (v) return v->rank();
        else {
            v = insert(value);
            const int ans = v->rank();
            return erase(v), ans;
        }
    }
    inline int size() {return root->size-2;}
};

char cmd[30];
int n;
Splay<int, INT_MAX> splay;
int seq[MAXN], len = 0;

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    scanf("%d", &n);
    while(n--) {
        scanf("%s", cmd);
        if (cmd[1] == 'o') {
            if (len == 0) {
                printf("Invalid\n");
            } else {
                int v = seq[len-1]; len--;
                printf("%d\n", v);
                splay.erase(splay.find(v));
            }
        } else if (cmd[1] == 'e') {
            int k = splay.size();
            k = (k + 1) >> 1;
            if (k == 0) {
                printf("Invalid\n");
            } else {
                printf("%d\n", splay.select(k));
            }
        } else if (cmd[1] == 'u') {
            int x; scanf("%d", &x);
            splay.insert(x);
            seq[len++] = x;
        }
    }
    return 0;
}

二分+bit

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

const int MAX_N = 100010;

int bit[MAX_N+1], n;

void update(int i, int x) {
    while (i <= n) {
        bit[i] += x;
        i += i & -i;
    }
}

int sum(int i) {
    int ans = 0;
    while (i) {
        ans += bit[i];
        i -= i & -i;
    }
    return ans;
}

int kth(int k) {
    int lo = 1, hi = n+1;
    while (lo < hi) {
        int mi = (lo + hi) >> 1;
        if (k <= sum(mi)) {
            hi = mi;
        } else {
            lo = mi + 1;
        }
    }
    return lo;
}

char cmd[20];
int m;
int seq[MAX_N], len = 0;

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    scanf("%d", &m); len = 0;
    memset(bit, 0, sizeof(bit)); n = MAX_N;
    while (m--) {
        scanf("%s", cmd);
        if (cmd[1] == 'o') {
            if (len == 0) {
                printf("Invalid\n");
            } else {
                int v = seq[len-1]; len--;
                printf("%d\n", v);
                update(v, -1);
            }
        } else if (cmd[1] == 'u') {
            int x; scanf("%d", &x);
            seq[len++] = x;
            update(x, 1);
        } else if (cmd[1] == 'e') {
            int k = len; k = (k + 1) >> 1;
            if (k == 0) {
                printf("Invalid\n");
            } else {
                int v = kth(k);
                printf("%d\n", v);
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值