【洛谷1486】[NOI2004] 郁闷的出纳员(Splay的小运用)
大致题意: 你是一个公司的出纳员,现在有\(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的小运用)的更多相关文章
- 洛谷.1486.[NOI2004]郁闷的出纳员(Splay)
题目链接 /* BZOJ1503: 3164kb 792ms/824ms(新建节点) 洛谷 : 3.06mb 320ms/308ms(前一个要慢wtf 其实都差不多,但前者好写) 四种操作: A:所有 ...
- 洛谷P1486 [NOI2004]郁闷的出纳员(splay)
题目描述 OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资 ...
- 洛谷P1486 [NOI2004]郁闷的出纳员 [STL,平衡树]
题目传送门 郁闷的出纳员 题目描述 OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反 ...
- 洛谷 P1486 [NOI2004]郁闷的出纳员
题目描述 OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资 ...
- 洛谷 P1486 [NOI2004]郁闷的出纳员【Treap】题解+AC代码
题目描述 OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资 ...
- 洛谷P1486 [NOI2004]郁闷的出纳员
Code: #include<cstdio> #include<algorithm> using namespace std; struct Node{ int s,val,t ...
- BZOJ 1503: [NOI2004]郁闷的出纳员 splay
1503: [NOI2004]郁闷的出纳员 Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作 ...
- NOI2004 郁闷的出纳员 Splay
郁闷的出纳员 [问题描述] OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常, ...
- BZOJ[NOI2004]郁闷的出纳员 | Splay板子题
题目: 洛谷也能评测....还有我wa了10多次的记录233 题解: 不要想得太复杂,搞一个全局变量记录一下工资的改变量Delta,这样可以等询问的时候就输出val+Delta,然后插入的时候插入x- ...
- 【BZOJ1503】 [NOI2004]郁闷的出纳员 splay
splay模板题,都快把我做忧郁了. 由于自己调两个坑点. 1.删除时及时updata 2.Kth 考虑k满足该点的条件即r->ch[1]->size+1<=k && ...
随机推荐
- java 多线程学习笔记(二) -- IO密集型任务
IO密集型是指对IO操作较多的任务.下面以查询一些股票价格任务为例: YahooFinance.java public class YahooFinance { public static doubl ...
- Linux调优(文件系统)
查看单个文件是否发生碎片化(被存在磁盘非连续磁盘块上) # filefrag -v /var/log/messages 查看文件系统是否存在大量碎片(会显示空闲离散的块) # dumpe2fs /de ...
- JS模块
本文主要内容翻译自<Exploring ES6-upgrade to the next version of javascript> 模块系统 定义模块接口,通过接口 隐藏模块的内部实现, ...
- EventLoop-浏览器与Node.js--整理
近来面试中会遇到的问题,关于浏览器和Nodejs两个运行环境的Event loop. 整理值得阅读的优秀文章 参考文章: 1.不要混淆nodejs和浏览器的eventloop 2.nodejs官网关于 ...
- :input获得焦点时被弹出键盘挡住解决办法
这个是移动端非常常见的bug了,这里说下综合的解决办法,因为有时候你的办法就是会失效.. 上代码 /*input框调起输入法盖住输入问题*/$('input[type="text" ...
- 03.Spring IoC 容器 - 初始化
基本概念 Spring IoC 容器的初始化过程在监听器 ContextLoaderListener 类中定义. 具体由该类的的 configureAndRefreshWebApplicationCo ...
- LeetCode 260 Single Number III 数组中除了两个数外,其他的数都出现了两次,找出这两个只出现一次的数
Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ...
- mediawiki安装实现代码高亮的插件GeSHiHighLight
1.下载新版本的GeSHi(http://qbnz.com/highlighter) 2.解压,复制geshi目录到mediawiki的扩展目录(extensions)下(建议删除contrib和do ...
- Vertical roller mill from SBM
Vertical roller mill has many different forms, but it works basically the same. All of these forms o ...
- Dede友情链接和分页列表和内容分页去掉小圆点LI标签
我用了一个比较老式的模板,友情链接和列表页底下的一段分页导航会自动获取LI标签,导致错位.每段文字前还多出一个可恶的黑色实心小圆点,心想肯定是LI标签在搞怪,于是把模板文件和样式文件都翻看了一个底朝天 ...