1. 程式人生 > >[splay] NOI2004 郁悶的出納員

[splay] NOI2004 郁悶的出納員

typedef 全部 格式 freopen 正整數 tchar 沒有 sin amp

題目描述

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 郁悶的出納員