bzoj1503 鬱悶的出納員
阿新 • • 發佈:2018-12-15
Description
OIER公司是一家大型專業化軟體公司,有著數以萬計的員工。作為一名出納員,我的任務之一便是統計每位員工的 工資。這本來是一份不錯的工作,但是令人鬱悶的是,我們的老闆反覆無常,經常調整員工的工資。如果他心情好 ,就可能把每位員工的工資加上一個相同的量。反之,如果心情不好,就可能把他們的工資扣除一個相同的量。我 真不知道除了調工資他還做什麼其它事情。工資的頻繁調整很讓員工反感,尤其是集體扣除工資的時候,一旦某位 員工發現自己的工資已經低於了合同規定的工資下界,他就會立刻氣憤地離開公司,並且再也不會回來了。每位員 工的工資下界都是統一規定的。每當一個人離開公司,我就要從電腦中把他的工資檔案刪去,同樣,每當公司招聘 了一位新員工,我就得為他新建一個工資檔案。老闆經常到我這邊來詢問工資情況,他並不問具體某位員工的工資 情況,而是問現在工資第k多的員工拿多少工資。每當這時,我就不得不對數萬個員工進行一次漫長的排序,然後 告訴他答案。好了,現在你已經對我的工作了解不少了。正如你猜的那樣,我想請你編一個工資統計程式。怎麼樣 ,不是很困難吧?Input
Output
輸出行數為F命令的條數加一。 對於每條F命令,你的程式要輸出一行,僅包含一個整數,為當前工資第k多的員工所拿的工資數, 如果k大於目前員工的數目,則輸出-1。 輸出檔案的最後一行包含一個整數,為離開公司的員工的總數。Sample Input
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2
Sample Output
1020
-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; }