• HNOI2004 郁闷的出纳员(Splay)


    郁闷的出纳员

    OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?

    Input

    Output

    输出文件的行数为F命令的条数加一。对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1。输出文件的最后一行包含一个整数,为离开公司的员工的总数。

    Sample Input
    9 10
    I 60
    I 70
    S 50
    F 2
    I 30
    S 15
    A 5
    F 1
    F 2
    
    Sample Output
    10
    20
    -1
    2
    
    Hint

    I命令的条数不超过100000 A命令和S命令的总条数不超过100 F命令的条数不超过100000 每次工资调整的调整量不超过1000 新员工的工资不超过100000

    第一次写平衡树,在网上拷了一份板子,但是只懂了一部分,里面的求前驱后继的代码是我在别的代码里粘贴进去的,有待测试。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <time.h>
    #include <string>
    #include <map>
    #include <stack>
    #include <vector>
    #include <set>
    #include <queue>
    #define maxn 102
    const int MAXN=2e5+100;
    int lim;
    struct SplayTree {
        int sz[MAXN];
        int ch[MAXN][2];
        int pre[MAXN];
        int rt,top;
        inline void up(int x) {
            sz[x]  = cnt[x]  + sz[ ch[x][0] ] + sz[ ch[x][1] ];
        }
        inline void Rotate(int x,int f) {
            int y=pre[x];
            ch[y][!f] = ch[x][f];
            pre[ ch[x][f] ] = y;
            pre[x] = pre[y];
            if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;
            ch[x][f] = y;
            pre[y] = x;
            up(y);
        }
        inline void Splay(int x,int goal) { //将x旋转到goal的下面
            while(pre[x] != goal) {
                if(pre[pre[x]] == goal) Rotate(x, ch[pre[x]][0] == x);
                else   {
                    int y=pre[x],z=pre[y];
                    int f = (ch[z][0]==y);
                    if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);
                    else Rotate(y,f),Rotate(x,f);
                }
            }
            up(x);
            if(goal==0) rt=x;
        }
        inline void RTO(int k,int goal) { //将第k位数旋转到goal的下面
            int x=rt;
            while(sz[ ch[x][0] ] != k-1) {
                if(k < sz[ ch[x][0] ]+1) x=ch[x][0];
                else {
                    k-=(sz[ ch[x][0] ]+1);
                    x = ch[x][1];
                }
            }
            Splay(x,goal);
        }
        inline void vist(int x) {
            if(x) {
                printf("结点%2d : 左儿子  %2d   右儿子  %2d   %2d sz=%d
    ",x,ch[x][0],ch[x][1],val[x],sz[x]);
                vist(ch[x][0]);
                vist(ch[x][1]);
            }
        }
        inline void Newnode(int &x,int c) {
            x=++top;
            ch[x][0] = ch[x][1] = pre[x] = 0;
            sz[x]=1;
            cnt[x]=1;
            val[x] = c;
        }
        inline void init() {
            sum=ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
            rt=top=0;
            cnt[0]=0;
        }
        inline void Insert(int &x,int key,int f) {
            if(!x) {
                Newnode(x,key);
                pre[x]=f;
                Splay(x,0);
                return ;
            }
            if(key==val[x]) {
                cnt[x]++;
                sz[x]++;
                Splay(x,0);
                return ;
            } else if(key<val[x]) {
                Insert(ch[x][0],key,x);
            } else {
                Insert(ch[x][1],key,x);
            }
            up(x);
        }
        //找前驱
        inline int Get_pre(int r) {
            if(ch[r][0] == 0)return -1;//不存在
            r = ch[r][0];
            while(ch[r][1])r = ch[r][1];
            return r;
        }
        //找后继
        inline int Get_next(int r) {
            if(ch[r][1] == 0)return -1;
            r = ch[r][1];
            while(ch[r][0])r = ch[r][0];
            return r;
        }
        void del(int &x,int f) {
            if(!x) return ;
            if(val[x]>=lim) {
                del(ch[x][0],x);
            } else {
                sum+=sz[ch[x][0]]+cnt[x];
                x=ch[x][1];
                pre[x]=f;
                if(f==0) rt=x;
                del(x,f);
            }
            if(x)  up(x);
        }
        inline void update() {
            del(rt,0);
        }
        inline int find_kth(int x,int k) {
            if(k<sz[ch[x][0]]+1) {
                return find_kth(ch[x][0],k);
            } else if(k > sz[ ch[x][0] ] + cnt[x] )
                return find_kth(ch[x][1],k-sz[ch[x][0]]-cnt[x]);
            else {
                Splay(x,0);
                return val[x];
            }
        }
        int cnt[MAXN];
        int val[MAXN];
        int sum;
    } spt;
    int main() {
        int n;
        int m;
        char op[5];
        scanf("%d%d",&n,&m);
        int w=0;
        spt.init();
        while(n--) {
            int k;
            scanf("%s%d",op,&k);
            if(op[0]=='I') {
                if(k<m) {
                    continue;
                }
                spt.Insert(spt.rt,k-w,0);
            } else if(op[0]=='A') {
                w+=k;
            } else if(op[0]=='S') {
                w-=k;
                lim=m-w;
                spt.update();
            } else {
                int sz=spt.sz[spt.rt];
                if(k>sz)printf("-1
    ");
                else {
                    printf("%d
    ",spt.find_kth(spt.rt,sz-k+1)+w);
                }
            }
        }
        printf("%d
    ",spt.sum);
        return 0;
    }
  • 相关阅读:
    Query on The Trees(hdu 4010)
    背单词(bzoj 4567)
    P2819 图的m着色问题
    P1605 迷宫
    P1230 智力大冲浪
    P1082 同余方程
    P3372 【模板】线段树 1
    P2626 斐波那契数列(升级版)
    长生诀
    写给我第一个喜欢的男孩的歌
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/6275450.html
Copyright © 2020-2023  润新知