花了一两天真正的熟悉了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 ",treap.Ran(w)); } printf("%d ",ans - treap . size()); return 0; }
that is all.Thank you for watching.