[luogu1486][NOI2004]郁闷的出纳员

传送门

看到这题觉得是平衡树,因为有查找第k大和插入删除操作。

但是我不会平衡树啊……所以拿树状数组写了一个伪平衡树。

对于插入操作,直接插,但是要减掉一个rec值。这个rec是什么意思等下说。

对于删除操作,直接删就行了。

对于A,我们肯定不行把所有数字都加一遍,于是利用rec,使rec这个变量加上修改值。所以员工真正的工资 = 他们的值 + rec

对于S,同理。但是这里我们需要不断查询最小值,和工资标准比较,然后开始删。

对于查询操作,直接查第k大即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 600005
#define lowbit(x) (x&(-x))

struct disc {
    
    long long temp[MAXN],num[MAXN];
    int tot,cnt;
    disc() : tot(0),cnt(0) {}

    void add(long long x) {
        temp[++cnt] = x;
    }

    void unique() {
        std::sort(temp+1,temp+1+cnt);
        temp[0] = -2147483647;
        for(int i=1;i<=cnt;++i) 
            if(temp[i]!=temp[i-1]) num[++tot] = temp[i];
    }

    int sub(long long x) {
        int l = 1,r = tot;
        while(l<r) {
            int mid = (l+r+1)>>1;
            if(num[mid]>x) r = mid - 1;
            else l = mid;
        }
        return l;
    }

}d;

struct record {
    int num;
    char opt;
}R[MAXN];

int C[MAXN];
int N,line,count = 0,ans = 0;
long long rec = 0;

inline char get_opt() {
    char ch = getchar();
    while(ch!='I'&&ch!='A'&&ch!='S'&&ch!='F') ch = getchar();
    return ch;
}

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

inline void update(int x,int u) {
    for(;x<=d.tot;x+=lowbit(x)) C[x] += u;
}

inline int query(int x) {
    int ans = 0;
    for(;x>=1;x-=lowbit(x)) ans += C[x];
    return ans;
}

inline int find_rk(int rk) {
    int cur = 0,tot = 0;
    for(int i=(1<<20);i>=1;i>>=1) {
        cur += i;
        if(cur>d.tot||tot+C[cur]>=rk) cur -= i;
        else tot += C[cur];
    }
    return cur + 1;
}

inline void work() {
    while(count>0) {
        long long cur = d.num[ find_rk(1) ];
        if(cur + rec < line) {
            update( d.sub( cur ) , -1 );
            count --;
            ans ++;
        }
        else break;
    }
}

int main() {

    N = read(); line = read(); 
    for(int i=1;i<=N;++i) {
        
        R[i].opt = get_opt();
        R[i].num = read();
        
        if(R[i].opt=='I') d.add( R[i].num - rec );
        else if(R[i].opt=='A') rec += (long long)R[i].num;
        else if(R[i].opt=='S') rec -= (long long)R[i].num;

    }

    d.unique();

    rec = 0;
    for(int i=1;i<=N;++i) {  
        if(R[i].opt=='I'&&R[i].num>=line) {
            count++;
            update(d.sub( R[i].num - rec ),1);
        }
        else if(R[i].opt=='A') rec += (long long)R[i].num;
        else if(R[i].opt=='S') {
            rec -= (long long)R[i].num;
            work();
        }
        else if(R[i].opt=='F'){
            if(R[i].num>count) puts("-1");
            else printf("%lld\n",d.num[find_rk(count - R[i].num + 1)] + rec);
        }
    }

    printf("%d",ans);
    return 0;
}
posted @ 2018-12-21 13:31  Neworld1111  阅读(169)  评论(0)    收藏  举报