【BZOJ 1503】【NOI 2004】郁闷的出纳员
$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; }
NOI 2017 Bless All