[NOI2004]郁闷的出纳员【splay】

版权声明:https://blog.csdn.net/qq_41730082 https://blog.csdn.net/qq_41730082/article/details/87980947

题目链接


  一道splay的基础题吧,稍微加了些许新的思路就是得去考虑如何裁员,在基本的代码上进行了自己的一些改进了,也算是开始从照着模板敲开始到了根据自己的思路改变少许模板了,知道当值低于最小值Minn的时候,得去裁掉这名员工,我门最后还要知道到底裁掉了多少员工,这个就是将所有的size加起来就是了,然后过程上就是一些操作,就是对于全体的员工,我们给他们全体加或者是减工资的时候,得去记录这个目前的状态,然后进行一些改变即可。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e5 + 7;
int N, Minn, root, tot;
struct node
{
    int ff, val, ch[2], size, cnt;
    node() { ff = val = ch[0] = ch[1] = size = cnt = 0; }
}t[maxN];
void pushup(int rt) { t[rt].size = t[t[rt].ch[0]].size + t[t[rt].ch[1]].size + t[rt].cnt; }
void Rotate(int x)
{
    int y = t[x].ff, z = t[y].ff;
    int k = t[y].ch[1] == x;
    t[z].ch[t[z].ch[1] == y] = x;
    t[x].ff = z;
    t[y].ch[k] = t[x].ch[k^1];
    t[t[x].ch[k^1]].ff = y;
    t[x].ch[k^1] = y;
    t[y].ff = x;
    pushup(y);  pushup(x);
}
void Splay(int x, int goal)
{
    while(t[x].ff != goal)
    {
        int y = t[x].ff, z = t[y].ff;
        if(z != goal) (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? Rotate(x) : Rotate(y);
        Rotate(x);
    }
    if(!goal) root = x;
}
void insert(int x)
{
    int u = root, ff = 0;
    while(u && x != t[u].val)
    {
        ff = u;
        u = t[u].ch[x>t[u].val];
    }
    if(u) t[u].cnt++;
    else
    {
        u = ++tot;
        if(ff) t[ff].ch[x>t[ff].val] = u;
        t[u].ch[0] = t[u].ch[1] = 0;
        t[u].ff = ff;
        t[u].val = x;
        t[u].cnt = t[u].size = 1;
    }
    Splay(u, 0);
}
void Find(int x)
{
    int u = root;
    if(!u) return;
    while(t[u].ch[x>t[u].val] && x != t[u].val) u =t[u].ch[x>t[u].val];
    Splay(u, 0);
}
int Next(int x, int f)
{
    Find(x);
    int u = root;
    if(t[u].val >= x && f) return u;    //取上"="号目的在于直接删除
    if(t[u].val <= x && !f) return u;
    u = t[u].ch[f];
    while(t[u].ch[f^1]) u = t[u].ch[f^1];
    return u;
}
int Kth(int x)
{
    int u = root;
    if(t[u].size < x) return -1;
    while(true)
    {
        int y = t[u].ch[1];
        if(x > t[y].size + t[u].cnt)
        {
            x -= t[y].size + t[u].cnt;
            u = t[u].ch[0];
        }
        else
        {
            if(t[y].size >= x) u = y;
            else return t[u].val;
        }
    }
}
char op[3];
int k;
int main()
{
    scanf("%d%d", &N, &Minn);
    root = tot = 0;
    int state = 0, level = 0;
    insert(INF);
    while(N--)
    {
        scanf("%s", op);
        scanf("%d", &k);
        if(op[0] == 'I')
        {
            if(k >= Minn) insert(k - state);
        }
        else if(op[0] == 'A') state += k;
        else if(op[0] == 'S')   //这里就需要裁员了
        {
            state -= k;
            int last = Next(Minn - state, 1);
            Splay(last, 0);
            level += t[t[root].ch[0]].size;
            t[t[root].ch[0]].size = t[t[root].ch[0]].cnt = 0;
            t[root].ch[0] = 0;
            pushup(root);
        }
        else
        {
            int ans = Kth(k + 1);
            if(ans != -1) ans += state;
            printf("%d\n", ans);
        }
    }
    printf("%d\n", level);
    return 0;
}
/*
9 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2
*/

  这次,在Next()函数,以及Kth()函数上做了些许改变,然后加上那个初识的insert(INF),就是为了避免在删除节点的时候会无根节点的状况。

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/87980947