首页 > 代码库 > _bzoj1503 [NOI2004]郁闷的出纳员【Splay】

_bzoj1503 [NOI2004]郁闷的出纳员【Splay】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1503

由于初始工资未达到下限而离开的员工不算在离开人数之内。。。坑爹。。。

然后就是写kth的时候,忘记考虑当前节点的值有可能出现了不止一次。。。

#include <cstdio>

const int maxn = 100005;

int n, min_salary, zengL, root, cnt = 1, t1, leave;
int ch[maxn][2], fa[maxn], siz[maxn], key[maxn], tm[maxn];
char opr;

inline void pushup(int x) {
	siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + tm[x];
}
inline void rotate(int x) {
	int y = fa[x];
	if (y == ch[fa[y]][0]) {
		ch[fa[y]][0] = x;
	}
	else {
		ch[fa[y]][1] = x;
	}
	fa[x] = fa[y];
	int dir = x == ch[y][1];
	ch[y][dir] = ch[x][dir ^ 1];
	fa[ch[x][dir ^ 1]] = y;
	ch[x][dir ^ 1] = y;
	fa[y] = x;
	pushup(y);
	pushup(x);
}
inline void splay(int x) {
	int p;
	char flag1, flag2;
	while (fa[x]) {
		p = fa[x];
		if (!fa[p]) {
			rotate(x);
		}
		else {
			flag1 = p == ch[fa[p]][1];
			flag2 = x == ch[p][1];
			if (flag1 ^ flag2) {
				rotate(x);
			}
			else {
				rotate(p);
			}
			rotate(x);
		}
	}
	root = x;
}
inline int houji(int val) {
	int rt = 0, x = root;
	while (x && val != key[x] + zengL) {
		if (val < key[x] + zengL) {
			rt = x;
			x = ch[x][0];
		}
		else {
			x = ch[x][1];
		}
	}
	return x? x: rt;
}
bool ist(int x, int val, int p, int dir) {
	if (!x) {
		++cnt;
		key[cnt] = val - zengL;
		tm[cnt] = 1;
		siz[cnt] = 1;
		fa[cnt] = p;
		ch[p][dir] = cnt;
		return true;
	}
	if (val == key[x] + zengL) {
		++tm[x];
		++siz[x];
		return false;
	}
	int d = val > key[x] + zengL;
	bool rt = ist(ch[x][d], val, x, d);
	pushup(x);
	return rt;
}
inline int kth(int k) {
	int x = root;
	while (k > siz[ch[x][1]] + tm[x] || k <= siz[ch[x][1]]) {
		if (k > siz[ch[x][1]] + tm[x]) {
			k -= siz[ch[x][1]] + tm[x];
			x = ch[x][0];
		}
		else {
			x = ch[x][1];
		}
	}
	return key[x] + zengL;
}

int main(void) {
	//freopen("in.txt", "r", stdin);
	scanf("%d%d", &n, &min_salary);
	key[1] = 2000000000;
	siz[1] = 1;
	tm[1] = 1;
	root = 1;
	while (n--) {
		while ((opr = getchar()) < ‘A‘);
		scanf("%d", &t1);
		if (opr == ‘I‘) {
			if (t1 >= min_salary && ist(root, t1, 0, 0)) {
				splay(cnt);
			}
		}
		else if (opr == ‘A‘ || opr == ‘S‘) {
			zengL += (opr == ‘A‘? t1: -t1);
			splay(houji(min_salary));
			leave += siz[ch[root][0]];
			ch[root][0] = 0;
			pushup(root);
		}
		else {
			printf("%d\n", t1 > siz[root] - 1? -1: kth(t1 + 1));
		}
	}
	printf("%d\n", leave);
	return 0;
}

  

_bzoj1503 [NOI2004]郁闷的出纳员【Splay】