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

比treap慢180ms,合格。(间接证明了treap也是一种常数很大的东西囧)

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <time.h>
using namespace std;

const int N = 101000,INF = 0x3f3f3f3f;
int dead,n,delta,total;

struct Node *nill;

struct Node {
        Node *ch[2],*fa;
        int val,sz;
        bool d() { return fa->ch[1]==this; }
        void setc(Node *o,int c) {
                ch[c] = o;
                o->fa = this;
                up();
        }
        void up() { 
                if (this==nill) return ;
                sz = ch[0]->sz + ch[1]->sz + 1; 
        }
}memo[N],*bat,*root;
void rot(Node *o) {
        int c = o->d();
        Node *tmp = o->fa;
        tmp->setc(o->ch[c^1],c);
        tmp->fa->setc(o,tmp->d());
        o->setc(tmp,c^1);
        o->fa->up();
}
void splay(Node *o,Node *p) {
        while (o->fa != p) {
                if (o->fa->fa!=p) {
                        o->d()==o->fa->d() ? rot(o->fa) : rot(o);
                }
                rot(o);
        }
}
void newNode(Node *&o,int val = 0) {
        o = bat ++;
        o->ch[0] = o->ch[1] = o->fa = nill;
        o->val = val;
        o->sz = 1;
}
void init() {
        bat = memo;
        newNode(nill); nill->sz = 0;
        root = nill;
}
Node *getK(int K) {
        Node *o = root;
        while (true) {
                if (K==o->ch[0]->sz+1) return o;
                if (o->ch[0]->sz >= K) {
                        o = o->ch[0];
                } else {
                        K -= o->ch[0]->sz + 1;
                        o = o->ch[1];
                }
        }
}
Node *getBig(int val) {
        Node *o = root;
        Node *ret;
        while (true) {
                if (o==nill) return ret;
                if (o->val >= val) {
                        ret = o;
                        o = o->ch[0];
                } else {
                        o = o->ch[1];
                }
        }
}
void ins(int x) {
        if (x<dead) return ;
        x -= delta;
        root = getBig(x);
        Node *p;
        splay(root,nill);
        newNode(p,x);
        p->setc(root->ch[0],0);
        root->setc(p,0);
}
void check() {
        int val = dead-delta;
        root = getBig(val);
        splay(root,nill);
        total += root->ch[0]->sz;
        root->setc(nill,0);
}
int query(int K) {
        if (root->sz-1 < K) return -1;
        K = root->sz-1 - K + 1;
        root = getK(K);
        splay(root,nill);
        return root->val + delta;
}
void show(Node *o) {
        if (o==nill) return ;
        show(o->ch[0]);
        printf("%d ",o->val);
        show(o->ch[1]);
}
void show() {
        show(root); puts("");
}
int main() {
//        freopen("in.txt","r",stdin);
//        freopen("out.txt","w",stdout);
        scanf("%d%d",&n,&dead);
        init();
        newNode(root,INF);
        while (n--) {
                char s[13];
                int x;
                scanf("%s%d",s,&x);
                if (s[0]=='I') {
                        ins(x);
                } else if (s[0]=='A') {
                        delta += x;
                } else if (s[0]=='S') {
                        delta -= x;
                        check();
                } else {
                        printf("%d\n",query(x));
                }
        }
        printf("%d\n",total);
//        printf("%.6f\n",(double)clock()/CLOCKS_PER_SEC);
        return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值