郁闷的出纳员

题目描述

思路

Treap树 + 延迟标记

代码

#include 
#include 
#include 
#include 

const int MAX = 1e5 + 5;
int n, m, rt, tot, pt;
char str[5];
int ans, inf = 0x3f3f3f3f;
struct Node {
    int lc, rc, cnt, size, pri, key, tag;
    #define lc(x) t[x].lc
    #define rc(x) t[x].rc
    #define cnt(x) t[x].cnt
    #define size(x) t[x].size
    #define pri(x) t[x].pri
    #define key(x) t[x].key
    #define tag(x) t[x].tag
    #define add(x) t[x].add
}t[MAX];

void pushdown(int r) {
    if (!tag(r)) return;
    if (lc(r)) {
        key(lc(r)) += tag(r);
        tag(lc(r)) += tag(r);
    } 
    if (rc(r)) {
        key(rc(r)) += tag(r);
        tag(rc(r)) += tag(r);
    }
    tag(r) = 0;
}
void pushup(int r) {
    size(r) = size(lc(r)) + size(rc(r)) + cnt(r);
}
void zig(int &r) {
    pushdown(r);
    pushdown(lc(r));
    int s = lc(r);
    lc(r) = rc(s);
    rc(s) = r;
    size(s) = size(r);
    pushup(r);
    r = s;
}
void zag(int &r) {
    pushdown(r);
    pushdown(rc(r));
    int s = rc(r);
    rc(r) = lc(s);
    lc(s) = r;
    size(s) = size(r);
    pushup(r);
    r = s;
}
void show(int x) {
    printf("%d %d %d %d %d %3d\n", size(x), lc(x), rc(x), key(x), pri(x), tag(x));
    if (lc(x)) show(lc(x));
    if (rc(x)) show(rc(x));
}
void insert(int &r, int k) {
    if (!r) { 
        r = ++tot;
        pri(r) = rand(), key(r) = k;
        lc(r) = rc(r) = 0;
        size(r) = cnt(r) = 1;
        tag(r) = 0;
        return;
    } 
    pushdown(r);
    if (k == key(r)) ++cnt(r), pushup(r);
    else if(k < key(r)) {
        insert(lc(r), k);
        pushup(r);
        if (pri(lc(r)) < pri(r)) zig(r); 
    } else {
        insert(rc(r), k);
        pushup(r);
        if (pri(rc(r)) < pri(r)) zag(r); 
    }
}

int del (int &r, int k) {
    int res = 0;
    pushdown(r);
    if (k >= key(r)) {
        if (rc(r) != 0) {
            pushdown(rc(r));
            zag(r);
            res = del(r, k);
            pushup(r);
            return res;
        } else {
            res = size(r);
            r = 0;
            return res;
        }
    }
    res = del(lc(r), k);
    pushup(r);
    return res;     
}

int queryPre(int k) {
    int r = rt, res = inf;
    while (r) {
        pushdown(r);
        if (k >= key(r)) res = key(r), r = rc(r);
        else r = lc(r);
    }
    return res;
}

int queryKth(int k) {
    int r = rt, res = inf;
    if (size(r) < k) return inf;
    while (r) {
        pushdown(r);
        if (size(rc(r)) < k && size(rc(r)) + cnt(r) >= k) return key(r);
        else if (size(rc(r)) >= k) r = rc(r);
        else {
            k -= size(rc(r)) + cnt(r);
            r = lc(r);
        }
    }
    return res;
}

inline int read() {
    int s = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    return s * f;
}

int main() {
    srand(time(NULL));
    n = read(), m = read();
    for (int i = 1, j, k; i <= n; ++i) {
        scanf("%s", str), j = read();
        // printf("%s %d\n", str, j);
        if (str[0] == 'I') {
            if (j >= m) insert(rt, j);
        } else if (str[0] == 'A') {
            tag(rt) += j;
            key(rt) += j;
        } else if (str[0] == 'S') {
            tag(rt) -= j;
            key(rt) -= j;
            k = queryPre(m - 1);
            if (k != inf) ans += del(rt, k);
        } else if (str[0] == 'F') {
            k = queryKth(j);
            if (k != inf) printf("%d\n", k);
            else printf("-1\n");
        }
    }
    printf("%d\n", ans);
    return 0;
}

你可能感兴趣的:(郁闷的出纳员)