【BZOJ 1503】【NOI 2004】郁闷的出纳员

时间:2021-09-25 00:42:59

$Splay$模板题。

复习一下伸展树的模板。

一定不要忘了push啊!!!

对于减工资后删掉员工的操作,我选择插入一个$min+delta_{减少的工资}$的节点,把它$Splay$到根,砍掉它自己和左子树,保留右子树,这样该走的员工就会从这个世界上消失啦~~~

#include<cstdio>
#include<cstring>
#include<algorithm>
#define read(x) x = getint()
using namespace std;
struct node {
node *ch[2], *fa;
int d, sz, sum, lazy;
bool pl() {return this->fa->ch[1] == this;}
void setc(node *r, bool c) {ch[c] = r; r->fa = this;}
void count() {sum = ch[0]->sum + ch[1]->sum + sz;}
void push() {
if (lazy != 0) {
ch[0]->lazy += lazy;
ch[1]->lazy += lazy;
ch[0]->d += lazy;
ch[1]->d += lazy;
lazy = 0;
}
}
}*ROOT, *null;
node pool[100003];
int top = 0, M, n, gone = 0;
namespace Splay{
void Build() {
null = &pool[0];
null->d = null->sz = null->sum = 0;
null->ch[0] = null->ch[1] = null->fa = null;
ROOT = null;
}
node *newnode() {
node *t = &pool[++top];
t->d = t->sz = t->sum = 0;
t->ch[0] = t->ch[1] = t->fa = null;
return t;
}
void rotate(node *r) {
node *f = r->fa; if (r == null || f == null) return;
bool c = r->pl();
if (f->fa == null) ROOT = r, r->fa = null;
else f->fa->setc(r, f->pl());
f->setc(r->ch[!c], c);
r->setc(f, !c);
f->count();
}
void update(node *r) {if (r != ROOT) update(r->fa); r->push();}
void splay(node *r, node *tar = null) {
update(r);
for(; r->fa != tar; rotate(r))
if (r->fa->fa != tar) rotate(r->pl() == r->fa->pl() ? r->fa : r);
r->count();
}
void ins(int num) {
if (ROOT == null) {
ROOT = newnode();
ROOT->d = num;
ROOT->sz = ROOT->sum = 1;
return;
}
node *r = ROOT;
while (1) {
r->push();
int k = r->d; bool c;
if (num < k) c = 0;
else if (num > k) c = 1;
else {++r->sz; ++r->sum; splay(r); return;}
if (r->ch[c] == null) {
r->ch[c] = newnode();
r->setc(r->ch[c], c);
r->ch[c]->sz = r->ch[c]->sum = 1;
r->ch[c]->d = num;
splay(r->ch[c]);
return;
} else r = r->ch[c];
}
}
void ins2(int num) {
node *r = ROOT; bool c;
while (1) {
r->push();
if (num <= r->d) c = 0;
else c = 1;
if (r->ch[c] == null) {
r->ch[c] = newnode();
r->setc(r->ch[c], c);
splay(r->ch[c]);
gone += ROOT->ch[0]->sum;
ROOT->ch[1]->fa = null;
ROOT = ROOT->ch[1];
return;
} else r = r->ch[c];
}
}
int kth(int k) {
node *r = ROOT;
while (r != null) {
r->push();
if (r->ch[1]->sum >= k) r = r->ch[1];
else if (r->ch[1]->sum + r->sz >= k) return r->d;
else k -= r->ch[1]->sum + r->sz, r = r->ch[0];
}
return 0;
}
} inline int getint() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = k * 10 + c - '0';
return k * fh;
}
int main() {
Splay::Build();
read(n); read(M);
int num;
for(int i = 1; i <= n; ++i) {
char c = getchar(); while (c < 'A' || c > 'Z') c = getchar();
switch (c) {
case 'I':
read(num);
if (num >= M)
Splay::ins(num);
break;
case 'A':
read(num);
ROOT->d += num;
ROOT->lazy += num;
ROOT->push();
break;
case 'S':
read(num);
Splay::ins2(num + M);
ROOT->d -= num;
ROOT->lazy -= num;
ROOT->push();
break;
case 'F':
read(num);
if (num > ROOT->sum) puts("-1");
else printf("%d\n", Splay::kth(num));
break;
}
}
printf("%d\n", gone);
return 0;
}