[splay] NOI2004 郁悶的出納員
題目描述
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 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2
輸出樣例#1: 復制
10
20
-1
2
說明
I命令的條數不超過100000
A命令和S命令的總條數不超過100
F命令的條數不超過100000
每次工資調整的調整量不超過1000
新員工的工資不超過100000
題解
- 看到題目中的查詢第k大,很容易想到使用平衡樹,但是本人蒟蒻,只學過splay,不向其他巨佬,花式切題,treap,權值線段樹,替罪羊樹,vector一個都不會.
- 操作中,因為A命令和S命令都是對於所有的員工而不是某一特定的區間,所以我們可以在外部統一存儲.特別地,對於A操作,我們不需要管,而對於S操作,我們可以找到第一個符合條件也就是(ming-p)(其中p為外部A或S存儲的值)的值,然後把它旋轉到根,這就需要我們開始時插入一個極大的值,保證可以查詢到符合條件的值,進行splay操作後,根節點左子樹都是小於它的值,我們把它全部扔掉
#include<bits/stdc++.h>
#define in(i) (i=read())
using namespace std;
typedef long long lol;
lol read() {
lol ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
return ans*f;
}
const int inf=2147483647;
lol n,minx,ans,tot,p,root;
struct node {
int ff,ch[2],cnt,size,val;
}t[100010];
void push_up(int x) {
t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
}
void rorate(int x) {
int y=t[x].ff,z=t[y].ff;
int k=(t[y].ch[1]==x);
t[z].ch[t[z].ch[1]==y]=x; t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1]; t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y; t[y].ff=x;
push_up(y); push_up(x);
}
void splay(int x,int goal) {
while(t[x].ff!=goal) {
int y=t[x].ff,z=t[y].ff;
if(z!=goal) (t[z].ch[0]==y)^(t[y].ch[0]==x)?rorate(x):rorate(y);
rorate(x);
}
if(!goal) root=x;
}
inline void find(int x) {
int u=root;
if(!u) return;
while(t[u].ch[x>t[u].val] && x!=t[u].val) u=t[u].ch[x>t[u].val];
splay(u,0);
}
inline void insert(int x) {
int u=root,ff=0;
while(u && t[u].val!=x) {
ff=u;
u=t[u].ch[x>t[u].val];
}
if(u) t[u].cnt++;
else {
u=++tot;
if(ff) t[ff].ch[x>t[ff].val]=u;
t[u].ch[0]=t[u].ch[1]=0;
t[u].ff=ff; t[u].val=x;
t[u].size=t[u].cnt=1;
}
splay(u,0);
}
inline int Next(int x,int f) {
find(x); int u=root;
if(t[u].val>=x && f) return u;
if(t[u].val<=x && !f) return u;
u=t[u].ch[f];
while(t[u].ch[f^1]) u=t[u].ch[f^1];
return u;
}
inline void Del(int x) {
int last=Next(x,0),next=Next(x,1);
splay(last,0); splay(next,last);
int del=t[next].ch[0];
if(t[del].cnt>1) {
t[del].cnt--;
splay(del,0);
}
else t[next].ch[0]=0;
}
int kth(int x) {
int u=root;
if(t[u].size<x) return -inf;
while(1) {
int y=t[u].ch[1];
if(x>t[y].size+t[u].cnt) {
x-=t[y].size+t[u].cnt;
u=t[u].ch[0];
}
else
if(x<=t[y].size) u=y;
else return t[u].val;
}
}
int main()
{
//freopen("unhappy.in","r",stdin);
//freopen("unhappy.out","w",stdout);
in(n);in(minx);
int lg=0;
insert(inf);
for(lol i=1;i<=n;i++) {
char ch; lol k;
cin>>ch; in(k);
if(ch=='I') {
if(k>=minx) insert(k-p),lg++;
}
else if(ch=='A') p+=k;
else if(ch=='S') {
p-=k;
int f=Next(minx-p,1);
splay(f,0);
ans+=t[t[root].ch[0]].size;
lg-=t[t[root].ch[0]].size;
t[t[root].ch[0]].size=t[t[root].ch[0]].cnt=0;
t[root].ch[0]=0;
push_up(root);
}
else if(ch=='F') {
int x=kth(k+1);
if(x==-inf) cout<<-1<<endl;
else cout<<x+p<<endl;
}
}
cout<<ans<<endl;
return 0;
}
博主蒟蒻,隨意轉載.但必須附上原文鏈接
http://www.cnblogs.com/real-l/
[splay] NOI2004 郁悶的出納員