您的位置:首页 > 其它

BZOJ 1503 [NOI2004]郁闷的出纳员 (Splaytree)

2014-02-13 21:29 483 查看
用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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: