【Luogu】P1486郁闷的出纳员(Splay)

  题目链接

  名副其实的调了一下午……

  每做一道题都是对我那不规范的Splay代码的刀刻斧凿一般的修正啊……

  Splay。如果有一批员工不干了,那就找还能干的薪水最少的员工,把它splay到根,删除它的左子树。

  然后其他地方加一下标记乱搞就行,这个标记……跟NOIP蚯蚓那个题很像。qwq。

  

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cstdlib>
#define maxn 1000200
using namespace std;

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

int CNT;
long long ans;
struct Splay{
    struct Node{
        int    sum,size,fa,e[2],val;
    }tree[maxn];
    int point,tot,root;
    Splay(){point=tot=root=0;    }
    inline int iden(int x){    return x==tree[tree[x].fa].e[0]?0:1;    }
    inline void connect(int x,int fa,int how){    tree[x].fa=fa;    tree[fa].e[how]=x;    }
    inline void update(int x){    tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+tree[x].sum;    }
    inline void rotate(int x){
        int y=tree[x].fa;    int r=tree[y].fa;
        if(root==y)    root=x;
        int sony=iden(x);    int sonr=iden(y);
        int b=tree[x].e[sony^1];
        connect(b,y,sony);
        connect(y,x,sony^1);
        connect(x,r,sonr);
        update(y);    update(x);
    }
    void splay(int pos,int to){
        to=tree[to].fa;
        while(tree[pos].fa!=to){
            if(tree[tree[pos].fa].fa==to)    rotate(pos);
            else
                if(iden(pos)==iden(tree[pos].fa)){
                    rotate(tree[pos].fa);
                    rotate(pos);
                }
                else{    rotate(pos);    rotate(pos);    }
        }
    }
    int create(int val,int fa){
        tree[++tot].val=val;    tree[tot].fa=fa;
        tree[tot].sum=tree[tot].size=1;
        return tot;
    }
    int build(int val){
        if(root==0){    root=create(val,0);    return root;    }
        int now=root;
        while(now){
            tree[now].size++;
            if(tree[now].val==val){    tree[now].sum++;    return now;    }
            int nxt=val<tree[now].val?0:1;
            if(tree[now].e[nxt]==0){
                connect(create(val,now),now,nxt);
                update(now);
                return tot;
            }
            now=tree[now].e[nxt];
        }
        return 0;
    }
    inline void insert(int val){
        int p=build(val);
        if(++CNT==50){
            CNT=0;
            splay(p,root);
        }
    }
    inline int find(int val){
        int now=root;
        while(now){
            if(tree[now].val==val)    return now;
            int nxt=val<tree[now].val?0:1;
            now=tree[now].e[nxt];
        }
        return 0;
    }
    int upper(int val){
        int now=root,ans=root;
        while(now){
            if(tree[now].val==val)    return now;
            if(val<tree[now].val){
                ans=now;
                now=tree[now].e[0];
            }
            else    now=tree[now].e[1];
        }
        return ans;
    }
    void dele(int val){
        int deal=upper(val);
        if(tree[deal].val<val){
            ans+=tree[root].size;
            root=0;
            return;
        }
        splay(deal,root);
        ans+=tree[tree[deal].e[0]].size;
        tree[tree[deal].e[0]].fa=0;
        tree[deal].e[0]=0;
        update(deal);
    }
    int arank(int rnk){
        int now=root;
        while(rnk){
            int used=tree[now].size-tree[tree[now].e[1]].size;
            if(tree[tree[now].e[0]].size<rnk&&used>=rnk)    return tree[now].val;
            if(rnk<=used)    now=tree[now].e[0];
            else{
                rnk-=used;
                now=tree[now].e[1];
            }
        }
        if(++CNT==50&&now){
            splay(now,root);
            CNT=0;
        }
        return tree[now].val;
    }
    int query(int rnk,long long tag){
        if(tree[root].size<rnk)    return -1;
        return arank(tree[root].size-rnk+1)+tag;
    }
}s;
long long tag=0;
int main(){int n=read(),m=read();
    for(int i=1;i<=n;++i){
        char c[10];int x;
        scanf("%s%d",c,&x);
        switch(c[0]){
            case 'I':
                if(x>=m)    s.insert(x-tag);    break;
            case 'A':    tag+=x;    break;
            case 'S':
                tag-=x;    s.dele(m-tag);    break;
            case 'F':    printf("%d\n",s.query(x,tag));    break;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2018-01-17 19:40  Konoset  阅读(204)  评论(0编辑  收藏  举报