1. 程式人生 > 其它 >P1486 [NOI2004] 鬱悶的出納員

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\)
  • AS 命令的總條數不超過 \(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;
}