bzoj1503 鬱悶的出納員

Description

OIER公司是一家大型專業化軟件公司,有着數以萬計的員工。做爲一名出納員,個人任務之一即是統計每位員工的
工資。這原本是一份不錯的工做,可是使人鬱悶的是,咱們的老闆反覆無常,常常調整員工的工資。若是他心情好
,就可能把每位員工的工資加上一個相同的量。反之,若是心情很差,就可能把他們的工資扣除一個相同的量。我
真不知道除了調工資他還作什麼其它事情。工資的頻繁調整很讓員工反感,尤爲是集體扣除工資的時候,一旦某位
員工發現本身的工資已經低於了合同規定的工資下界,他就會馬上氣憤地離開公司,而且不再會回來了。每位員
工的工資下界都是統一規定的。每當一我的離開公司,我就要從電腦中把他的工資檔案刪去,一樣,每當公司招聘
了一位新員工,我就得爲他新建一個工資檔案。老闆常常到我這邊來詢問工資狀況,他並不問具體某位員工的工資
狀況,而是問如今工資第k多的員工拿多少工資。每當這時,我就不得不對數萬個員工進行一次漫長的排序,而後
告訴他答案。好了,如今你已經對個人工做了解很多了。正如你猜的那樣,我想請你編一個工資統計程序。怎麼樣
,不是很困難吧?

Input

第一行有兩個非負整數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是一個正整數。
在初始時,能夠認爲公司裏一個員工也沒有。
I命令的條數不超過100000 
A命令和S命令的總條數不超過100 
F命令的條數不超過100000 
每次工資調整的調整量不超過1000 
新員工的工資不超過100000

Output

輸出行數爲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
 
直接用Treap來維護第K大公司。
每來一個員工若是給的工資大於指望,那麼就扔進Treap裏面。
加工資直接循環,減工資時,若是當期那點小於指望,就刪了。
注意幾個細節:
刪點重複的直接一塊兒刪。
必定要先刪點,而後再減工資,要否則刪一半時二叉搜索樹性質沒法保證。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <queue>
#define in(a) a=read()
#define MAXN 200010
#define REP(i,k,n)  for(int i=k;i<=n;i++)
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')
            f=-1;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-'0';
    return x*f;
}
struct node{
    int data,l,r,key,c,size;
}tree[MAXN];
int n,m,total,root,fair[MAXN],ans;
int dis=0;
inline void update(int i){
    tree[i].size=tree[tree[i].l].size+tree[tree[i].r].size+tree[i].c;
    return ;
}
inline int ran(){
    int t=rand();
    return (t*68901935LL)%2147483647;
}
inline void zag(int &i){
    int t=tree[i].r;
    tree[i].r=tree[t].l;
    tree[t].l=i;
    tree[t].size=tree[i].size;
    update(i);
    i=t;
    return ;
}
inline void zig(int &i){
    int t=tree[i].l;
    tree[i].l=tree[t].r;
    tree[t].r=i;
    tree[t].size=tree[i].size;
    update(i);
    i=t;
    return ;
}
inline void insert(int &i,int k){
    if(!i){
        i=++total;
        tree[i].data=k;
        tree[i].key=ran();
        tree[i].c=tree[i].size=1;
        return ;
    }
    tree[i].size++;
    if(tree[i].data==k)  tree[i].c++;
    else if(k<tree[i].data){
        insert(tree[i].l,k);
        if(tree[tree[i].l].key<tree[i].key)  zig(i);
    }
    else{
        insert(tree[i].r,k);
        if(tree[tree[i].r].key<tree[i].key)  zag(i);
    }
    return ;
}
inline void delate(int &i,int k){
    if(!i)  return ;
    if(i==k){
        if(!tree[i].l || !tree[i].r)  i=tree[i].l+tree[i].r;
        else  if(tree[tree[i].l].key<tree[tree[i].r].key)  zig(i),delate(i,k);
        else  zag(i),delate(i,k);
    }
    else  if(tree[k].data<tree[i].data)  tree[i].size-=tree[k].c,delate(tree[i].l,k);
    else  tree[i].size-=tree[k].c,delate(tree[i].r,k);
    return ;
}
inline int getnum(int i,int k){
    if(!i)  return -1;
    if(tree[tree[i].r].size>=k) return getnum(tree[i].r,k);
    k-=tree[tree[i].r].size;
    if(tree[i].c>=k){
        return tree[i].data;
    }
    k-=tree[i].c;
    return getnum(tree[i].l,k);
}
int main(){
    in(n);in(m);
    char c;
    int a;
    REP(Stan,1,n){
        cin>>c;in(a);
        if(c=='I'){
            if(a<m)  continue;
            insert(root,a);
        }
        if(c=='A')
            REP(i,1,total)  if(!fair[i])  tree[i].data+=a;
        if(c=='S'){
            REP(i,1,total){
                if(fair[i]) continue;
                if(tree[i].data-a<m){
                      ans+=tree[i].c,delate(root,i),fair[i]=1;
                }
            }
            REP(i,1,total)
                if(!fair[i])  tree[i].data-=a;
        }
        if(c=='F'){printf("%d\n",getnum(root,a));}
    }
    cout<<ans<<endl;
    return 0;
}
    
相關文章
相關標籤/搜索