题目大意:

给4种操作

I:添加一个员工工资信息

A:增加所有员工的工资

S:减少所有员工的工资

F:询问工资第k高的员工的工资情况

自己做的第一道splay树的题目,初学找找感觉

 #include <cstdio>
#include <cstring>
#include <iostream> using namespace std;
int n,m,w,limit;
const int N = ;
#define ls ch[x][0]
#define rs ch[x][1]
struct SplayTree{
//sum[i]记录i以及其子树中的点的总个数,cnt[i]记录与i号位置取值相等的点的个数
int val[N] , cnt[N] , sum[N];
int all; //统计离开公司的员工的总人数,也就是相当于计算删除的点的个数
int ch[N][];
int pre[N];
int rt , top; void init()
{
ch[][] = ch[][] = pre[] = sum[] = cnt[] = ;
all = rt = top = ;
} void newNode(int &x , int c)
{
x = ++top;
ch[x][] = ch[x][] = pre[x] = ;
cnt[x] = sum[x] = , val[x]=c;
}
//通过左右子节点更新父节点
void up(int x){
sum[x] = sum[ch[x][]]+sum[ch[x][]]+cnt[x];
} void Rotate(int x , int f) //f==1表示右旋,也就是x属于父亲的左子树上
{
int y=pre[x];
ch[y][!f] = ch[x][f];
pre[ch[x][f]]=y;
if(pre[y]) ch[pre[y]][ch[pre[y]][]==y]=x;
pre[x]=pre[y];
pre[y]=x;
ch[x][f]=y;
up(y);
} void Splay(int x , int goal)
{
while(pre[x] != goal){
if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][] == x);
else{
int y=pre[x] , z=pre[y];
int f=(ch[z][] == y);
if(ch[y][f] == x) Rotate(x , !f) , Rotate(x , f);
else Rotate(y,f) , Rotate(x,f);
}
}
up(x);
if(goal == ) rt = x;
} void insert(int &x , int key , int fa)
{
//一直向下找到空的叶子节点插入当前的值
if(!x){
newNode(x , key);
pre[x]=fa;
Splay(x , );
return;
}
if(key == val[x]){
cnt[x]++;
sum[x]++;
Splay(x,);
return ;
}
//点插入左子树
else if(key<val[x]){
insert(ch[x][] , key , x);
}
//点插入右子树
else {
insert(ch[x][] , key , x);
}
up(x);
} void del(int &x , int fa)
{
//一直访问到空的叶子节点结束
if(!x) return ;
//当前点的工资满足要求,那么只要考虑其左子树上要删除多少点
if(val[x] >= limit) del(ch[x][] , x);
else{
/*当前点的工资不满足要求,那么这个点和其左子树都是不满足要求的
,all记录当前点和左子树删除的点的总数*/
all+=sum[ch[x][]]+cnt[x];
x=ch[x][];
//当前点被删除,连接关系要进行修改
pre[x]=fa;
if(fa == ) rt = x;
del(x,fa);
}
if(x) up(x);
} void update()
{
del(rt , );
} int find_kth(int x , int k)
{
if(k<sum[ch[x][]]+) return find_kth(ch[x][] , k);
else if(k > sum[ch[x][]]+cnt[x])
return find_kth(ch[x][] , k-sum[ch[x][]]-cnt[x]);
else{
Splay(x , );
return x;
}
}
}spt; int main()
{
// freopen("a.in" , "r" , stdin);
char op[];
int t;
while(~scanf("%d%d" , &n , &m))
{
spt.init();
for(int i= ; i<n ; i++){
scanf("%s%d" , op , &t);
if(op[] == 'I'){
if(t<m)
continue;
spt.insert(spt.rt , t-w , );
}
else if(op[] == 'A') w+=t;
else if(op[] == 'S'){
w-=t;
limit=m-w;
spt.update();
}
else{
int sum = spt.sum[spt.rt];
if(t>sum) printf("-1\n");
else{
printf("%d\n" , spt.val[spt.find_kth(spt.rt , sum-t+)]+w);
}
}
// cout<<"sum: "<<spt.sum[spt.rt]<<endl;
}
printf("%d\n" , spt.all);
}
return ;
}

最新文章

  1. ffmpeg centos6.5上安装(测试 amr 转换为 mp3)
  2. BLE 信道
  3. 给Hi3518e的Uboot添加UDP广播收发功能
  4. 初识Android NDK
  5. LR学习笔记---参数设置 (转 温故而知新)
  6. Java虚拟机的功能
  7. hbase常用运维命令
  8. C++时间戳转化(涉及GMT CST时区转化)
  9. SignalR 2.0 系列: 开始使用SignalR 2.0
  10. 【转】objective-c基本数据类型之输出格式符
  11. python学习(3)
  12. 微软office MIME类型
  13. 用 Asterisk 搭建自己的免费 VoIP 服务器
  14. android studio创建一个最简单的跳转activity
  15. rem是怎么计算的
  16. 图解Go select语句原理
  17. Python的Pandas库简述
  18. ES3之cookie
  19. rails gem更换ruby-china源
  20. python 解析 yaml文件

热门文章

  1. Unity坐标系统
  2. poj3252Round Numbers
  3. 009全志R16平台tinav3.0下编译不过的问题
  4. Sublime折腾记录
  5. java实现汉诺塔算法
  6. 洛谷 P2153 [SDOI2009]晨跑
  7. 数据库系统概论(2)——Chap. 2 关系数据库基础
  8. example - 在这里插入一句话的简介
  9. QT_3
  10. OpenCV2:第三章 读取图像