花了一两天真正的熟悉了Treap,对于一个东西,本蒟蒻认为,不应该要会,还应会熟练的写,【像哈狗写这个只需十分钟】
好吧,话归正题 先推荐另类解法 戳进去
此题解法很多BIT , 权值线段树 ,各种平衡树(准备抽空写)。。。。 是一道很棒的模板题。
这道题我们把每次全体加的工资和减的弄到一个变量,姑且叫为w,把当前操作的数叫为k,当我们加工资时,肯定不会有员工退役把。。。所以直接将w 加上 k就行了
如果是减工资,就有可能有员工退役了,我们就应进行一次删除操作了。。。
那么如何删除呢?
先把w减去k,然后遍历。
我们遇到的节点的值 + w 如果大于等于工资下限的话,那么肯定只有可能左儿子中有小于工资下限的吧,那么就跑到它左儿子那里去。如果遇到节点的值是小于工资下限的,那么它右子树有可能有小于工资下限的,那么就一直左旋(这样就能不断地把大的旋上来),直到右节点的值是Null或当前节点的值是大于等于工资上限的,然后删除左儿子(子树)( 即把左边变为Null),如果当前节点也是小于工资上限的话也把当前节点赋为Null。。
至于加入新的节点的话,前面的w跟他毛关系不沾对吧,就把他的值减去w就行啦!
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<map>
const 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 {
private :
struct Node {
Node* son[2];
int size,num,data,hr;
Node () {}
Node (int data,Node *fl) : data(data) { son[0] = son[1] = fl; size = num = 1; hr = R233(); }
void update () { size = son[0] -> size + son[1] -> size + num; }
}*Null,*root,meme[N],*pool;
int ball,money;
void rotate (Node *&T,bool v) {
Node* Tt = T -> son[v];
T -> son[v] = Tt -> son[v^1];
Tt -> son[v^1] = T;
T -> update(); Tt -> update();
T = Tt;
}
void Delete (Node *&T) {
if(T == Null) return ;
while (T -> son[1] != Null && T -> data + money <= min1) T -> son[0] = Null , rotate (T , 1);
if(T -> data + money <= min1) {
if(T -> data + money < min1) T = Null;
else T -> son[0] = Null , T -> size = T -> num;
return;
}
Delete (T -> son[0]);
T -> update();
}
void Insert (Node *&T) {
if(T == Null) { T = new (pool++) Node (ball,Null); return ; }
if(T -> data == ball) { ++ T -> num; ++ T -> size; return ; }
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) {
if(T == Null) return -1;
if(T -> son[1] -> size >= ball) return Rank (T -> son[1]);
if(T -> son[1] -> size + T -> num >= ball) return T -> data;
ball -= T -> son[1] -> size + T -> num; return Rank (T -> son[0]);
}
public :
Treap () { Null = new Node(); Null -> size = Null -> num = 0; }
void clear() { root = Null; pool = meme; money = 0; }
void Ins (int xxx) { ball = xxx - money; Insert(root); }
void Rai (int xxx) { money += xxx; }
void Cut (int xxx) { money -= xxx; Delete(root); }
int Ran (int xxx) { ball = xxx; int k = Rank(root); return k == -1 ? -1 : k + money; }
int size () { return root -> size; }
}treap;
int ans;
char opt[10];
int main () {
scanf("%d%d",&Q,&min1);
treap.clear();
while (Q--) {
scanf("%s%d",opt,&w);
if(opt[0] == 'I' && w >= min1) {
treap.Ins(w);
++ans;
}
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.