题面
思路
这里一个小技巧,题目让我们给所有员工加减 k k k的工资,我们不需要真的去树里面加;
我们只需要维护一个偏移量,对这个偏移量进行加减即可;
接着考虑删除会导致什么情况;
删除可能会导致员工离职,我们只需要像链表一样去操作即可;
不断的迭代去删除;
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 3e5 + 10,INF = 2e9+7;
struct Node{
int lc,rc;
int key,val;
int cnt,size;
}tr[N];
int idx,root;
int new_node(int key){
int p = ++idx;
tr[p].key = key;
tr[p].val = rand();
tr[p].cnt = tr[p].size = 1;
return p;
}
void push_up(int p){
tr[p].size = tr[p].cnt + tr[tr[p].lc].size + tr[tr[p].rc].size;
}
void Rrotate(int &p){
int q = tr[p].lc;
tr[p].lc = tr[q].rc;
tr[q].rc = p;
p = q;
push_up(tr[p].rc);
push_up(p);
}
void Lrotate(int &p){
int q = tr[p].rc;
tr[p].rc = tr[q].lc;
tr[q].lc = p;
p = q;
push_up(tr[p].lc);
push_up(p);
}
void build(){
root = new_node(-INF);
tr[root].rc = new_node(INF);
push_up(root);
if(tr[tr[root].rc].val > tr[root].val){
Lrotate(root);
}
}
void insert(int &p,int key){
if(!p){
p = new_node(key);
return;
}
if(tr[p].key == key){
++tr[p].cnt;
}else if(tr[p].key > key){
insert(tr[p].lc,key);
if(tr[tr[p].lc].val > tr[p].val){
Rrotate(p);
}
}else{
insert(tr[p].rc,key);
if(tr[tr[p].rc].val > tr[p].val){
Lrotate(p);
}
}
push_up(p);
}
void erase(int &p,int key){
if(!p) return;
if(tr[p].key == key){
if(tr[p].cnt > 1){
--tr[p].cnt;
}
else if(tr[p].lc || tr[p].rc){
if(!tr[p].rc || tr[tr[p].lc].val > tr[tr[p].rc].val){
//右旋 增加要删除结点的深度
Rrotate(p);
erase(tr[p].rc,key);
}else{
Lrotate(p);
erase(tr[p].lc,key);
}
}else p = 0;//如果是叶子
}else if(tr[p].key > key){
erase(tr[p].lc,key);
}else{
erase(tr[p].rc,key);
}
push_up(p);
}
//根据rank查key->第k大
int query_key_by_rank(int p,int rank){
if(!p) return INF;
if(tr[tr[p].rc].size >= rank){
return query_key_by_rank(tr[p].rc,rank);
}
else if(tr[tr[p].rc].size + tr[p].cnt >= rank){
return tr[p].key;
}
else return query_key_by_rank(tr[p].lc,rank-tr[tr[p].rc].size-tr[p].cnt);
}
//查询小于key最大的数
int get_prev(int p,int key){
if(!p) return -INF;
if(tr[p].key >= key){
return get_prev(tr[p].lc,key);
}
return max(tr[p].key,get_prev(tr[p].rc,key));
}
void solve(){
int n,minn,offset = 0,leave = 0,now = 0;
cin >> n >> minn;
char opt;
int k;
build();
for(int i=1;i<=n;++i){
cin >> opt >> k;
if(opt == 'I'){
if(minn > k){
continue;
}
else{
insert(root,k - offset);
++now;
}
}
else if(opt == 'A'){
offset += k;
}
else if(opt == 'S'){
offset -= k;
//找所有满足小于minn - offset的值
int tar = minn - offset,key;
while((key = get_prev(root,tar))!=-INF){
erase(root,key);
++leave;
--now;
}
}
else{
if(now >= k) cout << offset+query_key_by_rank(root,k+1) << '\n';
else cout << -1 << '\n';
}
}
cout << leave << '\n';
}
int main(){
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
solve();
return 0;
}