zoukankan      html  css  js  c++  java
  • 【NOI2004】郁闷的出纳员

    https://daniu.luogu.org/problem/show?pid=1486

    由于每次调工资都是对全体员工,所以可以用一个标记来记录全体员工的工资偏移值。

    每次下调工资都有可能造成有员工的工资低于下界,这时需要将他们一起移除。可以用Splay来维护员工工资的集合。

    #include <iostream>
    using namespace std;
    namespace splay
    {
    enum direction
    {
        l = 0,
        r = 1
    };
    const int inf = 0x7fffffff;
    struct node *nil = 0;
    struct node
    {
        int val, cnt, size;
        node *ch[2];
        node(int v) : val(v), cnt(1), size(1) { ch[l] = ch[r] = nil; }
        int cmp(int v)
        {
            if (v == val || this == nil)
                return -1;
            else
                return (v < val) ? l : r;
        }
        int cmpkth(int k)
        {
            if (k <= ch[l]->size)
                return l;
            else if (k <= ch[l]->size + cnt)
                return -1;
            else
                return r;
        }
        void pullup() { size = cnt + ch[l]->size + ch[r]->size; }
    } * root;
    void init()
    {
        if (!nil)
            nil = new node(0);
        nil->cnt = nil->size = 0;
        nil->ch[l] = nil->ch[r] = nil;
        root = nil;
    }
    void rotate(node *&t, int d)
    {
        node *k = t->ch[d ^ 1];
        t->ch[d ^ 1] = k->ch[d];
        k->ch[d] = t;
        t->pullup();
        k->pullup();
        t = k;
    }
    void splay(node *&t, int v)
    {
        int d = t->cmp(v);
        if (d != -1 && t->ch[d] != nil)
        {
            int d2 = t->ch[d]->cmp(v);
            if (d2 != -1 && t->ch[d]->ch[d2] != nil)
            {
                splay(t->ch[d]->ch[d2], v);
                if (d == d2)
                {
                    rotate(t, d2 ^ 1);
                    rotate(t, d ^ 1);
                }
                else
                {
                    rotate(t->ch[d], d2 ^ 1);
                    rotate(t, d ^ 1);
                }
            }
            else
                rotate(t, d ^ 1);
        }
    }
    void splaykth(node *&t, int k)
    {
        int d = t->cmpkth(k);
        if (d == r)
            k -= t->ch[l]->size + t->cnt;
        if (d != -1)
        {
            int d2 = t->ch[d]->cmpkth(k);
            int k2 = (d2 == r) ? (k - t->ch[d]->ch[l]->size - t->ch[d]->cnt) : k;
            if (d2 != -1)
            {
                splaykth(t->ch[d]->ch[d2], k2);
                if (d == d2)
                {
                    rotate(t, d2 ^ 1);
                    rotate(t, d ^ 1);
                }
                else
                {
                    rotate(t->ch[d], d2 ^ 1);
                    rotate(t, d ^ 1);
                }
            }
            else
                rotate(t, d ^ 1);
        }
    }
    node *split(node *&t, int v) //t为大于等于v的树,返回严格小于v的树
    {
        splay(t, v);
        node *t1, *t2;
        if (t->val >= v)
        {
            t1 = t;
            t2 = t->ch[l];
            t->ch[l] = nil;
        }
        else
        {
            t1 = t->ch[r];
            t2 = t;
            t->ch[r] = nil;
        }
        t->pullup();
        t = t1;
        return t2;
    }
    node *join(node *t, node *t2)
    {
        if (t == nil)
            swap(t, t2);
        splay(t, inf);
        t->ch[r] = t2;
        t->pullup();
        return t;
    }
    void insert(node *&t, int v)
    {
        node *k = split(t, v);
        if (t != nil && v == t->val)
        {
            t->cnt++;
            t->size++;
        }
        else
            k = join(k, new node(v));
        t = join(k, t);
    }
    void remove(node *&t)
    {
        if (t != nil)
        {
            remove(t->ch[l]);
            remove(t->ch[r]);
            delete t;
            t = nil;
        }
    }
    }
    int n, minn, inc = 0, cnt = 0;
    int main()
    {
        using namespace splay;
        ios::sync_with_stdio(false);
        init();
        cin >> n >> minn;
        char c;
        int k;
        node *nd;
        while (n--)
        {
            cin >> c >> k;
            switch (c)
            {
            case 'I':
                if (k >= minn)
                    insert(root, k - inc);
                break;
            case 'A':
                inc += k;
                break;
            case 'S':
                inc -= k;
                nd = split(root, minn - inc);
                cnt += nd->size;
                remove(nd);
                break;
            case 'F':
                if (root->size < k)
                    cout << -1 << endl;
                else
                {
                    splaykth(root, root->size - k + 1);
                    cout << root->val + inc << endl;
                }
                break;
            }
        }
        cout << cnt << endl;
        return 0;
    }
  • 相关阅读:
    Suricata的输出
    Setting up IPS/inline for Linux in Suricata
    Suricata的初始化脚本
    Suricata的Reputation
    Suricata的配置
    Suricata的性能
    Suricata里的规则与Snort区别之处
    Suricata的命令行解释
    [转]ASP.NET 成员资格 Part.1(API)
    [转]ASP.NET MVC4+BootStrap 实战(一)
  • 原文地址:https://www.cnblogs.com/ssttkkl/p/7532172.html
Copyright © 2011-2022 走看看