【BZOJ1503】【NOI2004】郁闷的出纳员

【题目链接】

【思路要点】

  • 随便用个平衡树、线段树、块状链表、std::vector之类的数据结构维护一下就行了。
  • 时间复杂度\(O(NLogN)\)或\(O(N\sqrt{N})\)。

【代码】

#include<stdio.h>
#define MAXN	200000
struct data {
	int left, right, father, size, v, num; 
} tree[MAXN]; 
int n, m, l, tot, root, delta; 
void pushup(int x) {
	tree[x].size = tree[tree[x].left].size+tree[tree[x].right].size+1; 
}
void zig(int &x) {
	int y = tree[x].father; 
	int z = tree[y].father; 
	if (y == tree[z].left) tree[z].left = x; 
	else tree[z].right = x; 
	tree[x].father = z; 
	tree[y].left = tree[x].right; 
	tree[tree[x].right].father = y; 
	tree[x].right = y; 
	tree[y].father = x; 
	pushup(y); 
	pushup(x); 
	if (y == root) root = x; 	
}
void zag(int &x) {
	int y = tree[x].father; 
	int z = tree[y].father; 
	if (y == tree[z].left) tree[z].left = x; 
	else tree[z].right = x; 
	tree[x].father = z; 
	tree[y].right = tree[x].left; 
	tree[tree[x].left].father = y; 
	tree[x].left = y; 
	tree[y].father = x; 
	pushup(y); 
	pushup(x); 
	if (y == root) root = x; 	
}
void splay(int &x) {
	while (tree[x].father != 0) {
		if (tree[tree[x].father].left == x) zig(x); 
		else zag(x); 
	}
}
void insert(int k) {
	if (root == 0) {
		root = ++tot; 
		tree[tot].num = k; 
		tree[tot].size = 1; 
		return; 
	}
	int p = root, z; 
	while (p != 0) {
		z = p; 
		tree[p].size++; 
		if (k<tree[p].num) p = tree[p].left; 
		else p = tree[p].right; 
	}
	if (k<tree[z].num) tree[z].left = ++tot; 
	else tree[z].right = ++tot; 
	tree[tot].num = k; 
	tree[tot].size = 1; 
	tree[tot].father = z; 
	splay(tot); 
}
int dec(int &x, int f)
{
	if (x == 0) return 0; 
	int k; 
	if (tree[x].num+delta<m) {
		k = dec(tree[x].right, x)+tree[tree[x].left].size+1; 
		tree[tree[x].right].size = tree[x].size-k; 
		x = tree[x].right; 
		tree[x].father = f; 
	}
	else {
		k = dec(tree[x].left, x); 
		tree[x].size -= k; 
	}
	return k; 
}
int find(int &x, int k) {
	if (k <= tree[tree[x].right].size) return find(tree[x].right, k); 
	if (k == tree[tree[x].right].size+1) return tree[x].num; 
	return find(tree[x].left, k-tree[tree[x].right].size-1); 
}
int main() {
	scanf("%d%d", &n, &m); 
	int k; 
	char c[1]; 
	for (int i = 1; i <= n; i++) {
		scanf("%s%d", &c, &k); 
		if (c[0] == 'I' and k >= m) insert(k-delta); 
		if (c[0] == 'A') delta += k; 
		if (c[0] == 'S') {delta -= k; l += dec(root, 0); }; 
		if (c[0] == 'F') printf("%d\n", k <= tree[root].size?find(root, k)+delta:-1); 
	}
	printf("%d\n", l); 
	return 0; 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值