点此看题面

大致题意: 你是一个公司的出纳员,现在有\(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. 学习笔记:首次进行JUnit+Ant构建自动的单元测试(一)

    指导博客:https://blog.csdn.net/Cceking/article/details/51692010 基于软件测试的需求,使用JUnit+Ant构建自动的单元测试. IDE:ecli ...

  2. loj#6517. 「雅礼集训 2018 Day11」字符串(回滚莫队)

    传送门 模拟赛的时候纯暴力竟然骗了\(70\)分-- 首先对于一堆\(g\)怎么计算概率应该很好想,用总的区间数减去不合法的区间数就行了,简而言之对\(g\)排个序,每一段长为\(d\)的连续序列的区 ...

  3. 运算符优先级 (JavaScript)

    运算符优先级描述了在计算表达式时执行运算的顺序.先执行具有较高优先级的运算,然后执行较低优先级的运算.例如,先执行相乘,再执行相加. JavaScript 运算符     下表列出了 JavaScri ...

  4. POJ1031 Fence

    题目来源:http://poj.org/problem?id=1031 题目大意: 有一个光源位于(0,0)处,一个多边形的围墙.围墙是“全黑”的,不透光也不反射光.距光源r处的光强度为I0=k/r, ...

  5. python中深复制和浅复制区别

    在python中,对象赋值实际上是对象的的引用,当创建一个对象,然后把它赋值给另外一个变量的时候,python没有拷贝这个对象,而只是拷贝了这个对象的引用,多以就出现了浅复制,即复制后原对象改变后,复 ...

  6. 错误:正在解析文件 '/var/lib/dpkg/updates/0004'

    sudo rm /var/lib/dpkg/updates/* sudo apt-get update

  7. LeetCode 232 Implement Queue using Stacks 两个栈实现队列

    class MyQueue { public: /** Initialize your data structure here. */ MyQueue() { } /** Push element x ...

  8. View转换为Bitmap及getDrawingCache

    View组件显示的内容可以通过cache机制保存为bitmap, 使用到的api有 void  setDrawingCacheEnabled(boolean flag),    Bitmap  get ...

  9. Regionals 2014 >> Asia - Taichung 7003 - A Balance Game on Trees 树形DP + 二维费用背包

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  10. <s:property>的用法

    1,访问Action值栈中的普通属性: <s:property value="attrName"/> 2,访问Action值栈中的对象属性(要有get set方法):  ...