点此看题面

大致题意: 你是一个公司的出纳员,现在有\(n\)个操作,操作有4种:新来一个员工、增加全体员工工资、减少全体员工工资、查询第\(k\)多的工资。若一个员工的工资在某一时刻低于合同上的工资\(m\),他会立刻离开公司。要你回答每一个询问并统计出离开公司的人数。

平衡树

比较显然,这是一道平衡树的题目。

至于用哪一种平衡树,我感觉这题用\(Splay\)比较方便吧!

这道题目的关键就在于,如何解决增加全体员工工资减少全体员工工资

其实,直接用一个变量\(flag\)来存储每个员工的工资变化情况即可

每当增加全体员工工资,我们直接修改变量的值即可。

但是,如果减少全体员工工资,我们就要考虑是否有员工的工资低于\(m\),此时就需要工资低于\(m-flag\)的员工从树上删去,那么,我们可以把树上\(m-flag\)的前驱找到,然后将其用\(Splay\)操作旋转直至根节点,将此次要删去的员工数给统计下来后,将根节点更新为根节点的右儿子即可。

还有一个要注意的细节就是,每当新增一个员工时,由于之前每次调整工资时他都不在,所以要先将其工资减去\(flag\),然后再插入\(Splay\)中。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define LL long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))
#define N 100000
int pp_=0;char ff[100000],*A=ff,*B=ff,pp[100000];
using namespace std;
int n,m,rt,tot=0,ans=0,flag=0;
struct splay
{
int Son[2],Cnt,Size,Val,Father;
}node[N+5];
inline void read(int &x)
{
x=0;int f=1;char ch;
while(!isdigit(ch=tc())) f=ch^'-'?1:-1;
while(x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
x*=f;
}
inline void write(int x)
{
if(x<0) pc('-'),x=-x;
if(x>9) write(x/10);
pc(x%10+'0');
}
inline int Which(int x)//判断当前节点是其父亲节点的左儿子还是右儿子
{
return node[node[x].Father].Son[1]==x;
}
inline void PushUp(int x)//更新当前节点信息
{
node[x].Size=node[node[x].Son[0]].Size+node[node[x].Son[1]].Size+node[x].Cnt;
}
inline void Rotate(int x,int &k)//将当前节点上旋
{
int fa=node[x].Father,grandpa=node[fa].Father,d=Which(x);
if(fa^k) node[grandpa].Son[Which(fa)]=x;
else k=x;
node[x].Father=grandpa,node[fa].Son[d]=node[x].Son[d^1],node[node[x].Son[d^1]].Father=fa,node[x].Son[d^1]=fa,node[fa].Father=x,PushUp(fa),PushUp(x);
}
inline void Splay(int x,int &k)//将x节点旋转至指定位置k
{
for(int fa=node[x].Father;x^k;fa=node[x].Father)//只要x还没到目标位置就一直Rotate
{
if(fa^k) Rotate(Which(fa)^Which(x)?x:fa,k);
Rotate(x,k);
}
}
inline void Insert(int &x,int val,int fa)//插入一个值为val的数
{
if(!x) {node[x=++tot].Val=val,node[x].Cnt=node[x].Size=1,node[x].Father=fa,node[x].Son[0]=node[x].Son[1]=0,Splay(x,rt);return;}
if(node[x].Val==val) {++node[x].Cnt,Splay(x,rt);return;}
if(node[x].Val>val) Insert(node[x].Son[0],val,x);
else Insert(node[x].Son[1],val,x);
}
inline int get_val(int rk)//求出排名为rk的数的值
{
int x=rt;
while(x)
{
if(node[node[x].Son[0]].Size>=rk) x=node[x].Son[0];
else if(node[node[x].Son[0]].Size+node[x].Cnt>=rk) {Splay(x,rt);return node[x].Val;}
else rk-=node[node[x].Son[0]].Size+node[x].Cnt,x=node[x].Son[1];
}
}
inline int get_pre(int val)//求出val的前驱的节点编号
{
int x=rt,pre=0;
while(x)
{
if(node[x].Val<val) pre=x,x=node[x].Son[1];
else x=node[x].Son[0];
}
return pre;
}
inline void Delete(int val)//删除小于val的数
{
int k=get_pre(val);//k记录val的前驱
if(k) Splay(k,rt),ans+=node[node[rt].Son[0]].Size+node[rt].Cnt,rt=node[rt].Son[1],PushUp(rt);//将k旋转至根节点,然后更新ans,删除这些节点
}
int main()
{
register int i;
for(read(n),read(m),i=1;i<=n;++i)
{
char op;int x;while(!isalpha(op=tc()));read(x);
switch(op)
{
case 'I':if(x>=m) Insert(rt,x-flag,0);break;//增加一个新的员工
case 'A':flag+=x;break;//增加全体员工的工资
case 'S':Delete(m-(flag-=x));break;//减少全体员工的工资,删去工资少于m的员工
case 'F':if(node[rt].Size<x) pc('-'),pc('1');else write(get_val(node[rt].Size-x+1)+flag);pc('\n');break;//查询元素,由于询问的是从大到小的排名,所以要求的从小到大的排名就是rt的size减去询问的排名然后再加1
}
}
return write(ans),fwrite(pp,1,pp_,stdout),0;//最后输出答案
}

【洛谷1486】[NOI2004] 郁闷的出纳员(Splay的小运用)的更多相关文章

  1. 洛谷.1486.[NOI2004]郁闷的出纳员(Splay)

    题目链接 /* BZOJ1503: 3164kb 792ms/824ms(新建节点) 洛谷 : 3.06mb 320ms/308ms(前一个要慢wtf 其实都差不多,但前者好写) 四种操作: A:所有 ...

  2. 洛谷P1486 [NOI2004]郁闷的出纳员(splay)

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

  3. 洛谷P1486 [NOI2004]郁闷的出纳员 [STL,平衡树]

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

  4. 洛谷 P1486 [NOI2004]郁闷的出纳员

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

  5. 洛谷 P1486 [NOI2004]郁闷的出纳员【Treap】题解+AC代码

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

  6. 洛谷P1486 [NOI2004]郁闷的出纳员

    Code: #include<cstdio> #include<algorithm> using namespace std; struct Node{ int s,val,t ...

  7. BZOJ 1503: [NOI2004]郁闷的出纳员 splay

    1503: [NOI2004]郁闷的出纳员 Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作 ...

  8. NOI2004 郁闷的出纳员 Splay

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

  9. BZOJ[NOI2004]郁闷的出纳员 | Splay板子题

    题目: 洛谷也能评测....还有我wa了10多次的记录233 题解: 不要想得太复杂,搞一个全局变量记录一下工资的改变量Delta,这样可以等询问的时候就输出val+Delta,然后插入的时候插入x- ...

  10. 【BZOJ1503】 [NOI2004]郁闷的出纳员 splay

    splay模板题,都快把我做忧郁了. 由于自己调两个坑点. 1.删除时及时updata 2.Kth 考虑k满足该点的条件即r->ch[1]->size+1<=k && ...

随机推荐

  1. 不要忽视Web编程中的小细节

    概述:长时间以来,我们创造了某些在构造和范围内用以提升网站易用性的约定和实践.然后在我们进行web编程的时候总有一些疏忽和纰漏.这里总结了一些web编程时容易出现的小错误,并给出了相应的补救方法,希望 ...

  2. KVM虚拟机CPU绑定性能调优(宿主机上操作)

    获取kvm的pid ps -ef | grep kvm 通过pid找到vcpu在那个物理cpu上,没有绑定固定物理cpu时,执行下面命令可以看出vcpu在不同的物理cpu上切换重复执行 ps -eLo ...

  3. UVALive - 4223(hdu 2926)

    ---恢复内容开始--- 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2962 Trucking Time Limit: 20000/10000 MS ...

  4. leetcode--Learn one iterative inorder traversal, apply it to multiple tree questions (Java Solution)

    will show you all how to tackle various tree questions using iterative inorder traversal. First one ...

  5. Java面向对象_抽象类、接口

    一.抽象类 概   念:很多具有相同特征和行为的对象可以抽象为一个类:很多具有相同特征和行为的类可以抽象为一个抽象类 关键字:abstract 规   则:1.抽象类可以没有抽象方法,有抽象方法的类必 ...

  6. SpringBoot | 第零章:前言

    缘起 前段时间公司领导叫编写一两课关于springboot的基础知识培训课程,说实话,也是今年年初才开始接触了SpringBoot这个脚手架,使用了之后才发现打开了一个新世界.再之后也没有一些系统的学 ...

  7. notepad++上配置ruby执行环境

    1.安装NppExec 插件 2.按快捷键F6,在弹出框中输入如下命令: npp_save  cd "$(CURRENT_DIRECTORY)"  jruby "$(FI ...

  8. Eclipse下git如何创建分支

    1.项目–Team–Switch To –New Branch 2.Branch name 填写自己的版本号,然后Finish即可 3.将分支内容Push到远程服务器上

  9. hibernate课程 初探单表映射2-2 hibernate常用配置

    1 hibernate.cfg.xml常用配置: show_sql 控制台打印sql format_sql 控制台将sql排版 hbm2ddl.auto: create 删除表结构,重新建表并插值 u ...

  10. parameter与attribute的使用场合(转载自草原和大树)

    Attribute 和 Parameter 的区别 (1)HttpServletRequest类有setAttribute()方法,而没有setParameter()方法 (2)当两个Web组件之间为 ...