bzoj 3224 NOI2004郁闷的出纳员

NOI2004郁闷的出纳员

输入描述 Input Description

第一行有两个非负整数n和min。n表示下面有多少条命令,min表示工资下界。

接下来的n行,每行表示一条命令。命令可以是以下四种之一:

名称 格式 作用
I命令 I_k 新建一个工资档案,初始工资为k。如果某员工的初始工资低于工资下界,他将立刻离开公司。
A命令 A_k 把每位员工的工资加上k
S命令 S_k 把每位员工的工资扣除k
F命令 F_k 查询第k多的工资

_(下划线)表示一个空格,I命令、A命令、S命令中的k是一个非负整数,F命令中的k是一个正整数。

在初始时,可以认为公司里一个员工也没有。

输出描述 Output Description

输出文件的行数为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

题解:模板题吧,就是记录一个变化量搞一搞,裸的Treap,记录重复哪里搞错了,调了一个小时,无语了。

  1 #include<cstring>
  2 #include<cmath>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cstdio>
  6 
  7 #define ls tr[p].l
  8 #define rs tr[p].r
  9 #define N 100007
 10 using namespace std;
 11 inline int read()
 12 {
 13     int x=0,f=1;char ch=getchar();
 14     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
 15     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
 16     return x*f;
 17 }
 18 
 19 int n,m,sz,rt,ans,bh;
 20 char flag[3];
 21 struct Node
 22 {
 23     int l,r,val,siz,rnd,ct;//记录左儿子,右儿子,点值,该子树大小,随机的值,该点值出现的次数。 
 24 }tr[N];//最多多少个节点,就开多少空间 
 25 
 26 inline int rand(){
 27     static int seed = 2333;
 28     return seed = (int)((((seed ^ 998244353) + 19260817ll) * 19890604ll) % 1000000007);
 29 }
 30 inline void update(int p)
 31 {
 32     tr[p].siz=tr[ls].siz+tr[rs].siz+tr[p].ct;
 33 }
 34 void lturn(int &p)
 35 {
 36     int t=tr[p].r;tr[p].r=tr[t].l;tr[t].l=p;
 37     tr[t].siz=tr[p].siz;update(p);p=t;
 38 }
 39 void rturn(int &p)
 40 {
 41     int t=tr[p].l;tr[p].l=tr[t].r;tr[t].r=p;
 42     tr[t].siz=tr[p].siz;update(p);p=t;
 43 }
 44 void ins(int &p,int x)
 45 {
 46     if (p==0)
 47     {
 48         p=++sz;
 49         tr[p].siz=tr[p].ct=1,tr[p].val=x,tr[p].rnd=rand();
 50         return;
 51     }
 52     tr[p].siz++;
 53     if (tr[p].val==x) tr[p].ct++;
 54     else if (x>tr[p].val)
 55     {
 56         ins(tr[p].r,x);
 57         if (tr[rs].rnd<tr[p].rnd) lturn(p);
 58     }else
 59     {
 60         ins(tr[p].l,x);
 61         if (tr[ls].rnd<tr[p].rnd) rturn(p);
 62     }
 63 }
 64 int del(int &p,int x)
 65 {
 66     if (p==0) return 0;
 67     if (tr[p].val<x)
 68     {
 69         int t=tr[ls].siz+tr[p].ct;p=rs;
 70         return t+del(p,x);
 71     }
 72     else
 73     {
 74         int t=del(ls,x);tr[p].siz-=t;
 75         return t;
 76     }
 77 }
 78 int find_sz(int p,int x)
 79 {
 80     if (p==0) return 0;
 81     if (x<=tr[ls].siz) return find_sz(ls,x);
 82     x-=tr[ls].siz;
 83     if (x<=tr[p].ct) return tr[p].val+bh;
 84     x-=tr[p].ct;
 85     return find_sz(rs,x);
 86 }
 87 int main()
 88 {
 89     n=read(),m=read();
 90     for (int i=1;i<=n;i++)
 91     {
 92         scanf("%s",flag);int x=read();
 93         if (flag[0]=='I'&&x>=m) ins(rt,x-bh);
 94         if (flag[0]=='A') bh+=x;
 95         if (flag[0]=='S')
 96         {
 97             bh-=x;
 98             ans+=del(rt,m-bh);
 99         }
100         if (flag[0]=='F') printf("%d\n",(x>tr[rt].siz)?-1:find_sz(rt,tr[rt].siz-x+1));
101     }
102     printf("%d",ans);
103 }

 

posted @ 2017-12-06 20:56  Kaiser-  阅读(191)  评论(0编辑  收藏  举报