splay树解决NOI的郁闷的出纳员

#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;


struct node {
    int money, delta;
    int sum,ld,rd;
    node *lch,*rch,*fa;
    int calc_tot(){
        return (this==NULL ? 0:ld+rd+sum);
    }
}*root;


void pushdown(node *p)
{
    int delta;
    if (!p) return ;
    delta = p->delta;
    if (p->lch != NULL) p->lch->delta += delta;
    if (p->rch != NULL) p->rch->delta += delta;
    p->money += delta;
    p->delta = 0;
}


void splay(node *p,node *t)
{
    node *fa;
    if (p->fa == t) return ;
    fa = p->fa;
    pushdown(fa);
    pushdown(p);
    if (fa->lch == p){
        //left_rotate(p,fa);
        fa->lch = p->rch;
        if (p->rch != NULL) p->rch->fa = fa;
        p->rch = fa;
        p->fa =fa -> fa;
        if (fa->fa != NULL) {
            if (fa->fa->lch == fa) fa->fa->lch = p;
            else fa->fa->rch = p;
        }
        fa->fa = p;
        fa->ld = p->rd;
        p->rd = fa->calc_tot();
        splay(p,t);
    }
    else {
        //right_rotate(p,fa);
        fa->rch = p->lch;
        if (p->lch != NULL) p->lch->fa = fa;
        p->lch = fa;
        p->fa = fa->fa;
        if (fa->fa != NULL){
            if (fa->fa->lch == fa) fa->fa->lch = p;
            else fa->fa->rch = p;
        }
        fa->fa = p;
        fa->rd = p->ld;
        p->ld = fa->calc_tot();
        splay(p,t);
    }
}


void Insert(int x,int m)
{
    node *p=root,*q=NULL;
    if (x<m) return ;
    while (p != NULL) {
        pushdown(p);
        if (x< p->money){
            q = p;
            p->ld++;
            p = p->lch;
        }
        else if (x > p->money) {
            q = p;
            p->rd++;
            p = p->rch;
        }
        else {
            p->sum++;
            splay(p,NULL);
            root = p;
            return ;
        }
    }


    p=(node*)malloc(sizeof(node));
    p->fa = p->lch = p->rch = NULL;
    p->money = x;
    p->sum =1;
    p->delta = p->ld = p->rd = 0;


    if (q == NULL) q = p;
    else 
    if (q->money >x){
        q->lch = p;
        p->fa = q;
    }
    else {
        q->rch = p;
        p->fa = q;
    }
    splay(p,NULL);
    root = p;    
}


void add(int x)
{
    if (root) root->delta += x;
}


int del(int x,int m)
{
    node *p;
    int ans = 0;
    if (!root) return 0;
    root->delta -=x;
    Insert(m-1,m-1);
    ans+= root->lch->calc_tot()+root->sum-1;
    p = root->rch;
    if (p != NULL) p->fa=NULL;
    root = p;
    return ans;
}


int Find(int x,node *t)
{
    pushdown(t);
    if (x > t->calc_tot()) return -1;
    if (t->rd >= x) return Find(x,t->rch);
    if (x <= t->rd+t->sum) return t->money;
    if (x <= t->calc_tot()) return Find(x-t->rd-t->sum,t->lch);
    return -1;
}


int main()
{
    int n,m,x,ans,outcas=0;
    char op[5];
    scanf("%d%d",&n,&m);
    for (int i=0;i<n;i++){
        scanf("%s%d",op,&x);
        switch (op[0]) {
            case 'I':Insert(x,m);
                     break;
            case 'A':add(x);
                     break;
            case 'S':outcas += del(x,m);
                     break;
            case 'F':ans =Find(x,root);
                     printf("%d\n",ans);
                     break;
        }
    }
    printf("%d\n",outcas);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值