专栏文章
题解: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 条评论,欢迎与作者交流。
正在加载评论...