原題位址
花了一兩天真正的熟悉了treap,對於乙個東西,本蒟蒻認為,不應該要會,還應會熟練的寫,【像哈狗寫這個只需十分鐘】
好吧,話歸正題 先推薦另類解法 戳進去
此題解法很多bit , 權值線段樹 ,各種平衡樹(準備抽空寫)。。。。 是一道很棒的模板題。
這道題我們把每次全體加的工資和減的弄到乙個變數,姑且叫為w,把當前操作的數叫為k,當我們加工資時,肯定不會有員工退役把。。。所以直接將w 加上 k就行了
如果是減工資,就有可能有員工退役了,我們就應進行一次刪除操作了。。。
那麼如何刪除呢?
先把w減去k,然後遍歷。
我們遇到的節點的值 + w 如果大於等於工資下限的話,那麼肯定只有可能左兒子中有小於工資下限的吧,那麼就跑到它左兒子那裡去。如果遇到節點的值是小於工資下限的,那麼它右子樹有可能有小於工資下限的,那麼就一直左旋(這樣就能不斷地把大的旋上來),直到右節點的值是null或當前節點的值是大於等於工資上限的,然後刪除左兒子(子樹)( 即把左邊變為null),如果當前節點也是小於工資上限的話也把當前節點賦為null。。
至於加入新的節點的話,前面的w跟他毛關係不沾對吧,就把他的值減去w就行啦!
#include#include#include#include#include#include#include#include#includeconst int n = 1e5 + 7;
#define r12() ((rand()<<12) + (rand()<<7) + rand())
#define r233() (r12() % 4454515 + r12() % 45444211 + r12() % 144521 + 1)
int q,min1,w;
class treap
node (int data,node *fl) : data(data)
void update ()
}*null,*root,meme[n],*pool;
int ball,money;
void rotate (node *&t,bool v)
void delete (node *&t)
delete (t -> son[0]);
t -> update();
} void insert (node *&t)
if(t -> data == ball)
bool v = t -> data < ball;
insert(t -> son[v]);
if(t -> hr < t -> son[v] -> hr) rotate (t , v);
else t -> update();
} int rank (node *&t)
public :
treap ()
void clear()
void ins (int ***)
void rai (int ***)
void cut (int ***)
int ran (int ***)
int size ()
}treap;
int ans;
char opt[10];
int main ()
if(opt[0] == 'a') treap.rai(w);
if(opt[0] == 's') treap.cut(w);
if(opt[0] == 'f') printf("%d\n",treap.ran(w));
} printf("%d\n",ans - treap . size());
return 0;
}
that is all.thank you for watching.
NOI2004 鬱悶的出納員
大致題意就是對初始為空的數列的各種操作233 題解 splay啦 其中可能會遇到的幾個問題 1.如何刪去低於min的點 找到數列中min的後繼提為根,把根的左孩子丟 shan 了就完成了 很容易yy到的對吧 2.如何處理對當前數列中的數進行 k 開個全域性變數存整體的波動 值ff。那麼刪點的時候就把...
NOI2004 鬱悶的出納員
點此看題 這道題很新的一點就是加工資和減工資,這貌似要用到區間修改。但是細細想想,操作的物件是全樹,我們可以維護乙個累積的修改值,新加入乙個點的話要刪去之前的累計的修改值,對於減工資的情況,判斷有沒有低於最低的限制。注意如果乙個一來人就低於最低線,那麼這個人不被統計在最後的刪除人數中。include...
NOI 2004 鬱悶的出納員
oier公司是一家大型專業化軟體公司,有著數以萬計的員工。作為一名出納員,我的任務之一便是統計每位員工的工資。這本來是乙份不錯的工作,但是令人鬱悶的是,我們的老闆反覆無常,經常調整員工的工資。如果他心情好,就可能把每位員工的工資加上乙個相同的量。反之,如果心情不好,就可能把他們的工資扣除乙個相同的量...