[codevs1286]郁闷的出纳员

题目描述 Description

OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。

工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。

老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。

好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?

 
输入描述 Input Description

第一行有两个非负整数n和min。n表示下面有多少条命令,min表示工资下界。

接下来的n行,每行表示一条命令。命令可以是以下四种之一:

名称

格式

作用

I命令

I_k

新建一个工资档案,初始工资为k。如果某员工的初始工资低于工资下界,他将立刻离开公司。

A命令

A_k

把每位员工的工资加上k

S命令

S_k

把每位员工的工资扣除k

F命令

F_k

查询第k多的工资

_(下划线)表示一个空格,I命令、A命令、S命令中的k是一个非负整数,F命令中的k是一个正整数。

在初始时,可以认为公司里一个员工也没有。

输出描述 Output Description

输出文件的行数为F命令的条数加一。

对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1

输出文件的最后一行包含一个整数,为离开公司的员工的总数。

样例输入 Sample Input

9 10

I 60

I 70

S 50

F 2

I 30

S 15

A 5

F 1

F 2

样例输出 Sample Output

10

20

-1

2

数据范围及提示 Data Size & Hint
 10

20

-1

2

 平衡树全局标记tag,由于由时间先后顺序影响,插入一个元素X时只需要把X-tag插入即可,那样取出时直接X+tag就能完美避免那个问题了。只是一个小技巧。至于那些删除小于minn的值,由于最多把n个数删除,所以复杂度还是允许的,我们每一个节点记录最小值,详情处理请看程序:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
#define mem(a,b) memset(a,b,sizeof(a))
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
const int maxn=100010;
struct node
{
    int val,rnd;
    int cmp(int x)const
    {
        if(x==val)return -1;
        return x<val ? 0 : 1;
    }
}ns[maxn];
int tot,ch[2][maxn],size[maxn],rt,minv[maxn];
int New(int v)
{
    int o=++tot;ns[o].val=v;ns[o].rnd=rand();ch[0][o]=ch[1][o]=0;
    return o;
}
void del(int &o){ch[0][o]=ch[1][o]=ns[o].val=ns[o].rnd=size[o]=0;o=0;}
void maintain(int o)
{
    if(!o)return;size[o]=1;minv[o]=ns[o].val;
    if(ch[0][o])size[o]+=size[ch[0][o]],minv[o]=min(minv[o],minv[ch[0][o]]);
    if(ch[1][o])size[o]+=size[ch[1][o]],minv[o]=min(minv[o],minv[ch[1][o]]);
}
void rotate(int &o,int d)
{
    int k=ch[d^1][o];ch[d^1][o]=ch[d][k];ch[d][k]=o;
    maintain(o);o=k;
    return maintain(o);
}
void insert(int &o,int v)
{
    if(!o)
    {
        o=New(v);
        return maintain(o);
    }
    int d= v<ns[o].val ? 0 : 1;
    insert(ch[d][o],v);
    if(ns[ch[d][o]].rnd>ns[o].rnd)rotate(o,d^1);
    return maintain(o);
}
void remove(int &o,int v)
{
    if(!o)return;
    int d=ns[o].cmp(v);
    if(d==-1)
    {
        int t=o;
        if(ch[0][o] && ch[1][o])
        {
            int d2= ns[ch[0][o]].rnd>ns[ch[1][o]].rnd ? 1 : 0;
            rotate(o,d2);
            remove(ch[d2][o],v);
        }
        else if(!ch[0][o])o=ch[1][o];
        else o=ch[0][o];
        del(t);
    }
    else remove(ch[d][o],v);
    return maintain(o);
}
int kth(int &o,int k)
{
    if(!o || k<=0 || k>size[o])return -1;
    int s=size[ch[1][o]];
    if(k==s+1)return ns[o].val;
    if(k<=s)return kth(ch[1][o],k);
    else return kth(ch[0][o],k-s-1);
}
int m,minn,a,tag,cnt;
char tp;
int main()
{
    srand(325626);
    m=read();minn=read();
    while(m--)
    {
        cin>>tp;a=read();
        if(tp=='I')
        {
            if(a<minn){continue;}
            insert(rt,a-tag);
        }
        else if(tp=='A')tag+=a;
        else if(tp=='S')
        {
            tag-=a;
            while(minv[rt]+tag<minn && rt)remove(rt,minv[rt]),cnt++;
        }
        else if(tp=='F')
        {
            int tu=kth(rt,a);if(tu==-1)printf("%d\n",-1);
            else printf("%d\n",kth(rt,a)+tag);
        }
    }
    printf("%d\n",cnt);
    return 0;
}
View Code

 

posted @ 2017-05-31 11:17  小飞淙的云端  阅读(195)  评论(0编辑  收藏  举报