P1486 [NOI2004] 鬱悶的出納員
題面
OIER 公司是一家大型專業化軟體公司,有著數以萬計的員工。作為一名出納員,我的任務之一便是統計每位員工的工資。這本來是一份不錯的工作,但是令人鬱悶的是,我們的老闆反覆無常,經常調整員工的工資。如果他心情好,就可能把每位員工的工資加上一個相同的量。反之,如果心情不好,就可能把當前在公司的所有員工的工資扣除一個相同的量。我真不知道除了調工資他還做什麼其它事情。
工資的頻繁調整很讓員工反感,尤其是集體扣除工資的時候,一旦某位員工發現自己的工資已經低於了合同規定的工資下界,他就會立刻氣憤地離開公司,並且再也不會回來了。每位員工的工資下界都是統一規定的。每當一個人離開公司,我就要從電腦中把他的工資檔案刪去,同樣,每當公司招聘了一位新員工,我就得為他新建一個工資檔案。
老闆經常到我這邊來詢問工資情況,他並不問具體某位員工的工資情況,而是問現在工資第 \(k\) 多的員工拿多少工資。每當這時,我就不得不對數萬個員工進行一次漫長的排序,然後告訴他答案。
好了,現在你已經對我的工作了解不少了。正如你猜的那樣,我想請你編一個工資統計程式。怎麼樣,不是很困難吧?
如果某個員工的初始工資低於最低工資標準,那麼將不計入最後的答案內。
輸入格式
第一行有兩個整數 \(n\) 和 \(\min\)。\(n\) 表示下面有多少條命令,\(\min\) 表示工資下界。
接下來的 \(n\) 行,每行一個字元 \(x\) 和一個整數 \(k\),表示一條命令。命令可以是以下四種之一:
-
I k
新建一個工資檔案,初始工資為 \(k\)。如果某員工的初始工資低於工資下界,他將立刻離開公司。 -
A k
把每位員工的工資加上 \(k\) 。 -
S k
把每位員工的工資扣除 \(k\)。 -
F k
查詢第 \(k\) 多的工資。
在初始時,可以認為公司裡一個員工也沒有。
輸出格式
對於每條 F
命令,你的程式要輸出一行,僅包含一個整數,為當前工資第 \(k\) 多的員工所拿的工資數,如果 \(k\) 大於目前員工的數目,則輸出 \(-1\)。
輸出的最後一行包含一個整數,為離開公司的員工的總數。
請注意,初始工資低於工資下界的員工不算做離開公司的員工。
資料規模與約定
對於全部的測試點,保證:
-
I
命令的條數不超過 \(10^5\); -
A
和S
命令的總條數不超過 \(100\); -
F
命令的條數不超過 \(10^5\); - 每次工資調整的調整量不超過 \(10^3\);
- 新員工的工資不超過 \(10^5\)。
- \(0 \leq n \leq 3 \times 10^5\),\(0 \leq \text{min} \leq 10^9\),輸入的所有數字均在 \(32\) 位帶符號整形範圍內。
思路
暴力 std::vector
模擬,維護滿足 $ a_i \ge \min$ 的 std::vector
。
插入需要用到二分,不要用:std::lower_bound
!
程式碼
#include <bits/stdc++.h>
using namespace std;
int n,minv;
int leave_count=0;
vector<int> a;
int lowerbound(int be,int en,int k) {
int mid=be+en>>1;
if(be==en) {
return be;
}
int hj;
if(a[mid]<k) {
hj=lowerbound(be,mid,k);
} else {
hj=lowerbound(mid+1,en,k);
}
return hj;
}
void insert(int k){
if(k<minv){
return;
}
if(!a.empty()){
if(k<a[a.size()-1]){
a.push_back(k);
}
else{
a.insert(a.begin()+lowerbound(0,a.size()-1,k),k);
}
}
else{
a.push_back(k);
}
}
void add(int k){
for(int i=0;i<a.size();i++){
a[i]+=k;
}
}
void sub(int k){
for(int i=0;i<a.size();i++){
a[i]=a[i]-k;
if(a[i]<minv){
a.erase(a.begin()+i);
i--;
leave_count++;
}
}
}
int kth(int k){
if(k<a.size()+1){
return a[k-1];
}
else{
return -1;
}
}
int main(){
cin>>n>>minv;
for(int i=1,k;i<=n;i++){
char op;
cin>>op>>k;
if(op=='I'){
insert(k);
}
if(op=='A'){
add(k);
}
if(op=='S'){
sub(k);
}
if(op=='F'){
cout<<kth(k)<<'\n';
}
}
cout<<leave_count<<'\n';
return 0;
}