大视野1503-- [NOI2004]郁闷的出纳员SPLAY

Description

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

莫名其妙WA、、、非题解。。先备份下代码。。

#include <iostream> 
#include <cstdio> 
#include <cstring> 
using namespace std; 
#define inf 0x3f3f3f3f 
#define maxn 1000800 
#define LL long long int 
#define Key_value ch[ch[root][1]][0] 
  
struct SplayTree 
{ 
    int pre[maxn],key[maxn],ch[maxn][2],add[maxn],size[maxn],root,cnt; 
    void init() 
    { 
        root = cnt = 0; 
        size[0] = add[0] = ch[0][0] = ch[0][1] = key[0] = pre[0] = 0; 
    } 
  
    void NewNode(int & r,int father,int k) 
    { 
        r = ++cnt; 
        size[r] = 1; 
        pre[r] = father; 
        ch[r][0] = ch[r][1] = add[r] = 0; 
        key[r] = k; 
    } 
  
    int Insert(int k) 
    { 
        int r = root; 
        PushDown(r); 
        while(ch[r][key[r]<=k]) 
        { 
            r = ch[r][key[r]<=k]; 
            PushDown(r); 
        } 
        NewNode(ch[r][k>=key[r]],r,k); 
        Splay(ch[r][k>=key[r]],0); 
        return 1; 
    } 
  
    void Rotate(int x,int kind) 
    { 
        int y = pre[x]; 
        PushDown(y); 
        PushDown(x); 
        ch[y][!kind] = ch[x][kind]; 
        pre[ch[x][kind]] = y; 
        if(pre[y]) 
            ch[pre[y]][ch[pre[y]][1]==y] = x; 
        pre[x] = pre[y]; 
        ch[x][kind] = y; 
        pre[y] = x; 
        PushUp(y); 
    } 
  
    void Splay(int r,int goal) 
    { 
        PushDown(r); 
        while(pre[r] != goal) 
        { 
            int y = pre[r],z = pre[y]; 
            //PushDown(z);    PushDown(y);    PushDown(r); 
            if(z == goal) 
                Rotate(r,ch[y][0]==r); 
            else
            { 
                int kind = (ch[z][0] == y); 
                if(ch[y][kind] == r) 
                { 
                    Rotate(r,!kind); 
                    Rotate(r,kind); 
                } 
                else
                { 
                    Rotate(y,kind); 
                    Rotate(r,kind); 
                } 
            } 
        } 
        PushUp(r); 
        if(goal == 0)   root = r; 
    } 
  
    void PushDown(int r) 
    { 
        if(add[r]) 
        { 
            Update_Add(ch[r][0],add[r]); 
            Update_Add(ch[r][1],add[r]); 
            add[r] = 0; 
        } 
    } 
  
    void PushUp(int x) 
    { 
        int l = ch[x][0],r = ch[x][1]; 
        size[x] = size[l] + size[r] + 1; 
    } 
  
    void Update_Add(int r,int a) 
    { 
        if(!r)  return; 
        add[r] += a; 
        key[r] += a; 
    } 
  
    int Get_Kth(int r,int k) 
    { 
        int o = r; 
        while(o) 
        { 
            PushDown(o); 
            int t = size[ch[o][0]] + 1; 
            if(t == k)  return o; 
            else if(t > k) 
            { 
                o = ch[o][0]; 
            } 
            else
            { 
                o = ch[o][1]; 
                k -= t; 
            } 
        } 
    } 
  
    void solve(int n,int m) 
    { 
        init(); 
        int res = 0,ans = 0;//res表示剩下的人有多少个 
        while(n--) 
        { 
            char ope[2]; 
            scanf("%s",ope); 
            if(ope[0] == 'I') 
            { 
                int a;  scanf("%d",&a); 
                if(a < m)   continue; 
                else
                { 
                    Insert(a);  res++; 
                } 
            } 
            else if(ope[0] == 'S') 
            { 
                int a;  scanf("%d",&a); 
                int l = 1,r = res; 
                while(l < r) 
                { 
                    int mid = (l+r) >> 1; 
                    int x = Get_Kth(root,mid); 
                    if(key[x] - a >= m) 
                        r = mid; 
                    else l = mid+1; 
                } 
                ans += l-1; 
                if(l <= res) 
                { 
                    res -= l-1; 
                    int x = Get_Kth(root,l); 
                    Splay(x,0); 
                    pre[ch[root][0]] = 0; 
                    ch[root][0] = 0; 
                    PushUp(root); 
                    Update_Add(root,-a); 
                } 
                else
                { 
                    init(); res = 0; 
                } 
            } 
            else if(ope[0] == 'F') 
            { 
                int a;  scanf("%d",&a); 
                if(a > res) 
                { 
                    puts("-1"); continue; 
                } 
                a = res-a+1; 
                int x = Get_Kth(root,a); 
                printf("%d\n",key[x]); 
            } 
            else
            { 
                int a;  scanf("%d",&a); 
                if(res) 
                    Update_Add(root,a); 
            } 
        } 
        printf("%d\n",ans); 
    } 
}spt; 
  
int main() 
{ 
    //freopen("in.txt","r",stdin); 
    int n,m; 
    while(scanf("%d%d",&n,&m)==2) 
    { 
        spt.solve(n,m); 
    } 
    return 0; 
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值