【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;
}

  

posted @ 2016-04-03 11:33  abclzr  阅读(212)  评论(0编辑  收藏  举报