題目描述
oier公司是一家大型專業化軟體公司,有著數以萬計的員工。作為一名出納員,我的任務之一便是統計每位員工的工資。這本來是乙份不錯的工作,但是令人鬱悶的是,我們的老闆反覆無常,經常調整員工的工資。如果他心情好,就可能把每位員工的工資加上乙個相同的量。反之,如果心情不好,就可能把他們的工資扣除乙個相同的量。我真不知道除了調工資他還做什麼其它事情。
工資的頻繁調整很讓員工反感,尤其是集體扣除工資的時候,一旦某位員工發現自己的工資已經低於了合同規定的工資下界,他就會立刻氣憤地離開公司,並且再也不會回來了。每位員工的工資下界都是統一規定的。每當乙個人離開公司,我就要從電腦中把他的工資檔案刪去,同樣,每當公司招聘了一位新員工,我就得為他新建乙個工資檔案。
老闆經常到我這邊來詢問工資情況,他並不問具體某位員工的工資情況,而是問現在工資第k多的員工拿多少工資。每當這時,我就不得不對數萬個員工進行一次漫長的排序,然後告訴他答案。
好了,現在你已經對我的工作了解不少了。正如你猜的那樣,我想請你編乙個工資統計程式。怎麼樣,不是很困難吧?
如果某個員工的初始工資低於最低工資標準,那麼將不計入最後的答案內
輸入格式:
第一行有兩個非負整數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是乙個正整數。
在初始時,可以認為公司裡乙個員工也沒有。
輸出格式:
輸出檔案的行數為f命令的條數加一。
對於每條f命令,你的程式要輸出一行,僅包含乙個整數,為當前工資第k多的員工所拿的工資數,如果k大於目前員工的數目,則輸出-1。
輸出檔案的最後一行包含乙個整數,為離開公司的員工的總數。
輸入樣例#1:
9 10i 60
i 70
s 50
f 2i 30
s 15
a 5f 1
f 2
輸出樣例#1:
1020-1
2
i命令的條數不超過100000
a命令和s命令的總條數不超過100
f命令的條數不超過100000
每次工資調整的調整量不超過1000
新員工的工資不超過100000
1var2
opt :char;
3n,min,add,i,x,t,tot,cnt :longint;
4 left,right,key,size :array[0..200050] of
longint;56
procedure lrot(var
t:longint);
7var
8k :longint;
9begin
10 k:=right[t];
11 right[t]:=left[k];
12 left[k]:=t;
13 size[k]:=size[t];
14 size[t]:=size[left[t]]+size[right[t]]+1
;15 t:=k;
16end;17
18procedure rrot(var
t:longint);
19var
20k :longint;
21begin
22 k:=left[t];
23 left[t]:=right[k];
24 right[k]:=t;
25 size[k]:=size[t];
26 size[t]:=size[left[t]]+size[right[t]]+1
;27 t:=k;
28end;29
30procedure maintain(var
t:longint; flag:boolean);
31begin
32if
not flag then
33begin
34if size[left[left[t]]]>size[right[t]] then rrot(t) else
35if size[right[left[t]]]>size[right[t]] then
36begin
37lrot(left[t]);
38rrot(t);
39end
else
exit;
40end
else
41begin
42if size[right[right[t]]]>size[left[t]] then lrot(t) else
43if size[left[right[t]]]>size[left[t]] then
44begin
45rrot(right[t]);
46lrot(t);
47end
else
exit;
48end;49
maintain(left[t],false);
50maintain(right[t],true);
51maintain(t,true);
52maintain(t,false);
53end;54
55procedure insert(var
t:longint; v:longint);
56begin
57if t=0
then
58begin
59inc(tot);
60 t:=tot;
61 left[t]:=0
;62 right[t]:=0
;63 size[t]:=1
;64 key[t]:=v;
65exit;
66end;67
inc(size[t]);
68if vthen insert(left[t],v) else
insert(right[t],v);
69 maintain(t,v>=key[t]);
70end;71
72procedure delete(var
t:longint);
73begin
74if t=0
then
exit;
75if key[t]+add>=min then
76begin
77delete(left[t]);
78 size[t]:=size[left[t]]+size[right[t]]+1;79
endelse
80begin
81 t:=right[t];
82delete(t);
83end;84
end;
8586
function select(var
t:longint; v:longint):longint;
87begin
88if v=size[left[t]]+1
then
exit(key[t]);
89if v1
then
exit(select(left[t],v));
90 exit(select(right[t],v-size[left[t]]-1
));91
end;
9293
begin
94readln(n,min);
95 add:=0;96
for i:=1
to n do
97begin
98readln(opt,x);
99if (opt='
i') then
100begin
101if xthen
continue;
102inc(cnt);
103 insert(t,x-add);
104end
else
105if (opt='
a') then inc(add,x) else
106if (opt='
s') then
107begin
108dec(add,x);
109delete(t);
110end
else
if size[t]then writeln(-1) else writeln(select(t,size[t]+1-x)+add);
111end
;112 writeln(tot-size[t]);
113end.
NOI2004 鬱悶的出納員 平衡樹
ps splay依然不能一次寫對 總會寫出毛病,真是醉醉醉醉醉 這題難點在於變動工資,我們只需要變動工資k,表示工資現在增加了k。然後如果有員工進來,並且進的來,初始工資比最低工資高 那麼我們就把這個員工的工資,減去k這個值,加入到平衡樹中。刪人的的時候,只要查比 初始工資 工資變化量k 小的數字全...
noi 2004 鬱悶的出納員
原題位址 花了一兩天真正的熟悉了treap,對於乙個東西,本蒟蒻認為,不應該要會,還應會熟練的寫,像哈狗寫這個只需十分鐘 好吧,話歸正題 先推薦另類解法 戳進去 此題解法很多bit 權值線段樹 各種平衡樹 準備抽空寫 是一道很棒的模板題。這道題我們把每次全體加的工資和減的弄到乙個變數,姑且叫為w,把...
NOI2004 鬱悶的出納員
大致題意就是對初始為空的數列的各種操作233 題解 splay啦 其中可能會遇到的幾個問題 1.如何刪去低於min的點 找到數列中min的後繼提為根,把根的左孩子丟 shan 了就完成了 很容易yy到的對吧 2.如何處理對當前數列中的數進行 k 開個全域性變數存整體的波動 值ff。那麼刪點的時候就把...