【洛谷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 && ...
随机推荐
- 2017-10-19 NOIP模拟赛
Count(哈格朗日插值) 题解: 有个定理,另sum(x)表示小于等于x的数中与x互质的数的和 sum(x)=φ(x)*x/2 最后可知f(x)=x (f(1)=2) 当然打表能知道. 然 ...
- Mol Cell Proteomics. |马臻| psims-一个用于编写HUPO-PSI标准下的mzML和mzIdentML的python库
大家好,本周分享的是发表在MCP(MOLECULAR&CRLLULAR PROTEOMICS)上的一篇关于质谱数据处理和识别的文章,题目是psims - A Declarative Write ...
- js捕获activex事件
最近参与了一个项目,我的同事在开发一个ActiveX对象,我帮他编写JS脚本来调用这个对象,其中碰到蛮多问题,最难的就是如何响应由ActiveX对象返回的对象事件.正好,现在一起总结一下. 首先,我来 ...
- IDEA开发Spark的漫漫摸索(二)
1 新建Maven项目 特别提醒,Maven项目中有GropId和ArtifactId.GroupId是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构.一般Gru ...
- Java 8 Optional类使用的实践经验
前言 Java中空指针异常(NPE)一直是令开发者头疼的问题.Java 8引入了一个新的Optional类,使用该类可以尽可能地防止出现空指针异常. Optional 类是一个可以为null的容器对象 ...
- Effective Java第一节
第1条:考虑用静态工厂方法代替构造器 首先清楚什么是静态工厂方法? 静态工厂方法说白了就是在创建对象的时候,不是自己使用new关键字创建的,而是使用静态方法来对外提供自身的实例的方法. 比如: Fra ...
- CF446A DZY Loves Sequences 简单dp
DZY has a sequence a, consisting of n integers. We'll call a sequence ai, ai + 1, ..., aj (1 ≤ i ≤ j ...
- php类内方法使用类外变量和类外函数
如果要调用另一个类的属性和方法,直接实例化后调用就可以 但是要使用的变量和函数是独立的,不在本类或其他类里面,这时调用就要用下面的方法(本例是在同一个php文件里,如果不再同一个类文件可以requir ...
- Qt学习之网络编程(一)
一些说明 学了有一段时间的python了,小项目做了不少,最近由于项目需要,所以要回归老本行了,开始重点突击C++和qt.python的网络爬虫系列有时间就更吧. 获取本机网络信息 在网络应用中,经常 ...
- Luogu P2624 [HNOI2008]明明的烦恼 Prufer+组合+高精
好的我把标准版过了... 设$ r_i$为$i$的度数 首先,我们设 $ sum = \Sigma r_i-1$,$ tot $ 为所有能够确定度数的点 所以我们有 $ C ^ {sum} _{n-2 ...