专栏文章

题解:P1486 [NOI2004] 郁闷的出纳员

P1486题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipktsv1
此快照首次捕获于
2025/12/03 13:38
3 个月前
此快照最后确认于
2025/12/03 13:38
3 个月前
查看原文

Preface

看了一圈,大佬们各显神通,pb_ds,treap,splay,我都不会,献上一个树状数组做法。

Problem statement

维护数据结构,实现单点插入,全局加,全局减,全局第 k 小,同时如果减完后有点小于一个给定的限制就删除。

Solution

首先对于全局加减考虑不加每个点的值,而只是调整这个限制的值,同时记录目前调整的总量插入新点时减去,输出时加上就行了
现在实现插入,删除和全局第 k 小就可以用树状数组上二分解决了,具体可以看 oiwiki fenwick tree
CPP
/*

*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
int c[3000005], rang = 3000005;
void add(int x, int y){
	for(int i = x; i <= rang; i += i & -i){
		c[i] += y;
	}
}
int get(int x){
	int anst = 0;
	for(int i = x; i > 0; i -= i & -i){
		anst += c[i];
	} 
	return anst;
}
int kth(int k){
	int sum = 0, x = 0;
	//currently have a total of sum that are <= x
	for(int i = 35; i >= 0; i--){
		int powi = (1LL << i);
		if(x + powi <= rang && sum + c[x + powi] < k){
			//within range and within kth
			//we can just use c[x + powi] instead of using get
			//because we know all previous adding to x
			//all are 2 to the jth power where j > i, so powi
			//itself must be the lowbit of x + powi
			x += powi;
			sum += c[x];
		}
	}
	return x + 1;
}
int n, mi, tot, leav, num, INF = 5e5;
signed main(){
	cin>>n>>mi;
	mi += INF;
	while(n--){
		char typ;
		int x;
		cin>>typ>>x;
		if(typ == 'I'){
			if(x - tot + INF < mi){
				continue;
				//KEY BUG!!!
			}
			add(x - tot + INF, 1);
			num++;
		}
		if(typ == 'A'){
			mi -= x;
			tot += x;
		}
		if(typ == 'S'){
			mi += x;
			tot -= x;
			int curmi = kth(1);//smallest
			while(curmi < mi){
				//each will only be erased once we'll be fine
				add(curmi, -1);
				leav++;
				num--;
				//leave
				curmi = kth(1);
			}
		}
		if(typ == 'F'){
			if(x > num)cout<<-1<<endl;
			else cout<<kth(num - x + 1) + tot - INF<<endl;
		}
	}
	cout<<leav<<endl;
	return 0;
}
求赞。

评论

0 条评论,欢迎与作者交流。

正在加载评论...