用Splaytree实现插入,删除一个区间,求小于某值的个数。
题意有个坑。。初始工资小于工资下届不计入离开公司的总数。。
#include
const int maxn = 100000+10;
const int INF = 1<<30;
#define lson x->ch[0]
#define rson x->ch[1]
#define ket (root->ch[1]->ch[0])
struct NODE {
NODE *pre, *ch[2];
int val, id, sz, mark;
void down() {
if(mark) {
if(ch[0]->pre) {
ch[0]->mark += mark;
ch[0]->val += mark;
}
if(ch[1]->pre) {
ch[1]->mark += mark;
ch[1]->val += mark;
}
mark = 0;
}
}
void up() {
sz = ch[0]->sz + ch[1]->sz + 1;
}
}node[maxn], *null = &node[0], *root;
struct Splaytree {
int top;
void Rotate(NODE *x, int c) {
NODE *y = x->pre;
y->down(); x->down();
y->ch[!c] = x->ch[c];
if(x->ch[c] != null) x->ch[c]->pre = y;
x->pre = y->pre;
if(y->pre != null) y->pre->ch[ y->pre->ch[1]==y ] = x;
x->ch[c] = y; y->pre = x;
y->up();
}
void Splay(NODE *x, NODE *go) {
while(x->pre != go) {
if(x->pre->pre == go) Rotate(x, x->pre->ch[0] == x);
else {
NODE *y = x->pre, *z = y->pre;
int f = z->ch[1] == y;
if(y->ch[f] == x) Rotate(y, !f);
else Rotate(x, f);
Rotate(x, !f);
}
}
x->up();
if(go == null) root = x;
}
void RTO(int k, NODE *go) {
NODE *x = root;
x->down();
while(lson->sz != k) {
if(lson->sz > k) x = lson;
else {
k -= lson->sz + 1;
x = rson;
}
x->down();
}
Splay(x, go);
}
void debug(NODE *x) {
if(x != null) {
printf("节点: %2d 左儿子: %2d 右儿子: %2d size = %2d val = %2d\n",
x->id, x->ch[0]->id, x->ch[1]->id, x->sz, x->val);
x->down();
debug(x->ch[0]);
debug(x->ch[1]);
}
}
NODE *newnode(int c, NODE* f=null) {
NODE *x = &node[++top];
x->id = top;
x->val = c; x->sz = 1;
x->mark = 0; x->pre = f;
lson = rson = null;
return x;
}
void init() {
null->id = null->sz = null->val = null->mark = 0;
top = 0;
root = newnode(-INF);
root->ch[1] = newnode(INF, root);
root->ch[1]->up(); root->up();
}
void Insert(int c) {
NODE *x = root;
while(x->ch[ x->val <= c] != null) {
x->down();
x = x->ch[ x->val <= c];
}
x->down();
x->ch[ x->val <= c] = newnode(c, x);
Splay(x->ch[x->val<=c], null);
}
int find_cnt(NODE *x, int c) {
if(x == null) return 0;
x->down();
if(x->val < c) return lson->sz + 1 + find_cnt(rson, c);
else return find_cnt(lson, c);
}
void solve() {
init();
int n, m, k;
scanf("%d%d", &n, &m);
int ans = 0;
while(n--) {
char op[2];
scanf("%s%d", op, &k);
if(op[0] == 'I') {
if(k >= m) Insert(k);
}
else if(op[0] == 'A') {
root->mark += k; root->val += k;
}
else if(op[0] == 'S') {
root->mark -= k; root->val -= k;
int cnt = find_cnt(root, m);
if(cnt >= 2) {
ans += cnt-1;
RTO(0, null);
RTO(cnt, root);
ket = null;
root->ch[1]->up(); root->up();
}
}
else {
if(root->sz-2 < k) puts("-1");
else {
RTO(root->sz-2-k + 1, null);
printf("%d\n", root->val);
}
}
}
printf("%d\n", ans);
}
}spt;
int main(){
spt.solve();
return 0;
}