题面

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

输入格式

第一行有两个非负整数n和min。n表示下面有多少条命令,min表示工资下界。接下来的n行,每行表示一条命令。命令可以是以下四种之一:名称 格式 作用I命令 I_k 新建一个工资档案,初始工资为k。 如果某员工的初始工资低于工资下界,他将立刻离开公司。A命令 A_k 把每位员工的工资加上kS命令 S_k 把每位员工的工资扣除kF命令 F_k 查询第k多的工资_(下划线)表示一个空格,I命令、A命令、S命令中的k是一个非负整数,F命令中的k是一个正整数。在初始时,可以认为公司里一个员工也没有。I命令的条数不超过100000 A命令和S命令的总条数不超过100 F命令的条数不超过100000 每次工资调整的调整量不超过1000 新员工的工资不超过100000

输出格式

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

思路分析:splay 模板题难点是每个员工加钱的时候,由于每个员工到达时间不同,加钱显然没法同步,我们可以通过一个转化,将之前的加钱,在插入员工时减去即可转化成功细节见于代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;
const int N = 1e5 + 10, INF = 1e9;int n, m, delta;
struct node
{int s[2], p, v;int size;void init(int _v, int _p){v = _v, p = _p;size = 1;}
}tr[N];
int root, idx;void pushup(int x)
{tr[x].size = tr[tr[x].s[0]].size + tr[tr[x].s[1]].size + 1;
}void rotate(int x)
{int y = tr[x].p, z = tr[y].p;int k = tr[y].s[1] == x;tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z;tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y;tr[x].s[k ^ 1] = y, tr[y].p = x;pushup(y), pushup(x);
}void splay(int x, int k)
{while(tr[x].p != k){int y = tr[x].p, z = tr[y].p;if(z != k){if((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x);else rotate(y);}rotate(x);}if(!k) root = x;
}int insert(int v)
{int u = root, p = 0;while(u) p = u, u = tr[u].s[v > tr[u].v];u = ++ idx;if(p) tr[p].s[v > tr[p].v] = u;tr[u].init(v, p);splay(u, 0);return u;
}int get(int v)
{int u = root, res;while(u){if(tr[u].v >= v) res = u, u = tr[u].s[0];else u = tr[u].s[1];}return res;
}int get_k(int k)
{int u = root;while(u){if(tr[tr[u].s[0]].size >= k) u = tr[u].s[0];else if(tr[tr[u].s[0]].size + 1 == k) return tr[u].v;else k -= tr[tr[u].s[0]].size + 1, u = tr[u].s[1];}return -1;
}int main()
{scanf("%d%d", &n, &m);int L = insert(-INF), R = insert(INF);int tot = 0;while(n --){char op[2];int k;scanf("%s%d", op, &k);if(*op == 'I'){if(k >= m) k -= delta, insert(k), tot ++;}else if(*op == 'A') delta += k;else if(*op == 'S'){delta -= k;R = get(m - delta); // 查找比m - delta大的区间splay(R, 0), splay(L, R);tr[L].s[1] = 0; // 删除该区间的所有数pushup(L), pushup(R);}else{if(tr[root].size - 2 < k) puts("-1");else printf("%d\n", get_k(tr[root].size - k) + delta);}}printf("%d\n", tot - (tr[root].size - 2));return 0;
}

郁闷的出纳员(splay, 树状数组可做)相关推荐

  1. 【洛谷P1486】郁闷的出纳员【树状数组】

    题目描述 题目链接 分析 听说暴力能过 ,不敢打Treap/线段树. 很巧妙的一道题,第一次听说树状数组查询第k大/小的数. 定义树状数组为工资点上的人数,对于工资的整体增减可以通过设置变量p统一维护 ...

  2. poi 1990 MooFest(树状数组题目,转换成两个树状数组来做)较难的题目****

    1.http://poj.org/problem?id=1990 2.题目大意: 题意:FJ有n头牛,排列成一条直线(不会在同一个点),给出每头牛在直线上的坐标x.另外,每头牛还有一个自己的声调w,如 ...

  3. 950. 郁闷的出纳员(Splay树)

    OIER 公司是一家大型专业化软件公司,有着数以万计的员工. 作为一名出纳员,我的任务之一便是统计每位员工的工资. 这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资. ...

  4. poj 2352 Stars 线段树(先建后查/边建边查)/树状数组三种方法思路详解,带你深入了解线段树难度⭐⭐⭐★

    poj 2352 Stars 目录 poj 2352 Stars 1.树状数组 2.线段树,先建树后查找 3.线段树,边建树边查找 Description Astronomers often exam ...

  5. 【数据结构】树状数组 例题剖析

    目录 一.模板题 二.树状数组求逆序对 一.离散化 二.逆序对 三.待解决 P1428 小鱼比可爱 算法详解 一.模板题 模板题 题目描述 如题,已知一个数列,你需要进行下面两种操作: 将某一个数加上 ...

  6. HDU-1541 Stars 树状数组

    http://acm.hdu.edu.cn/showproblem.php?pid=1541 题义为给定N个点按照先x轴,后y轴坐标排序,求某一点的左下角的星星数量,刚开始用二维的树状数组来做,结果肯 ...

  7. hdu 3074 线段树 OR 树状数组

    比较基础的线段树,1A. 线段树: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 ...

  8. 树状数组的区间修改+查询

    首先看树状数组是用来求前缀和比较方便的一种数据结构 sum[i] = Sigma a[i] =Sum(bit[x]) 而区间修改也不难实现 就是引入一个差分数组del del[i]表示对i~n的修改 ...

  9. 数据结构--树状数组

    文章目录 1. 树状数组 2. 单点修改 3. 区间修改 4. 完整代码 5. 参考文献 1. 树状数组 类似数据结构:线段树(Segment Tree) 树状数组 跟 线段树 的区别: 树状数组能做 ...

最新文章

  1. python潜力开源项目_比较了1000多个Python开源项目,精选出这34个
  2. 【C语言编程练习】5.10寻找水仙数
  3. 深度学习基础知识介绍
  4. day11-元组与字典
  5. 前端学习(2779):项目功能介绍
  6. 笔记本电脑控制面板在哪_2020年滚筒洗衣机选购指南:滚筒洗衣机应该怎么选?哪一些滚筒洗衣机性价比更高?...
  7. VRTK之手柄事件监听以及重写StartUsing方法实现与物体的交互
  8. 总结---JavaScript数组
  9. win10截图快捷键
  10. kasp技术原理_Massarray技术——中高通量大样本的SNP检测利器!
  11. 新浪微博错误提示代码
  12. 有缘-无缘-惜缘-随缘
  13. 【MML】华为MML AAA接口联调,Java版本
  14. socks+proxychains网络代理
  15. Google搜索引擎使用技巧大全
  16. 关于MySQL认证的东东
  17. ios微信二维码无法长按识别的若干解决方案
  18. docker和vm不兼容遇到的坑
  19. 【UR #2】猪猪侠再战括号序列
  20. UG NX 12 拟合曲面

热门文章

  1. [文摘201009]演讲录全文:美国世界帝国战略与中国的危机 - 戴旭
  2. [数据与处理]归一化(连续值和离散值)
  3. 长生生物收到深交所重大违法强制退市决定,2019首支退市股!...
  4. 在avr单片机(atmega16)上移植freertos
  5. 微信小程序修改数据不刷新页面更新数据
  6. docker命令(一) —— docker logs 日志输出
  7. 开环快速峰值检波器电路
  8. 达梦数据库DCA培训课程总结
  9. VICKERS比例阀的组成及其工作原理
  10. Go语言上手-基础语言