NOI2004 郁闷的出纳员 Splay
郁闷的出纳员
【问题描述】
OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。
工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。
老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。
好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?
【输入文件】
第一行有两个非负整数n和min。n表示下面有多少条命令,min表示工资下界。
接下来的n行,每行表示一条命令。命令可以是以下四种之一:
名称 |
格式 |
作用 |
I命令 |
I_k |
新建一个工资档案,初始工资为k。如果某员工的初始工资低于工资下界,他将立刻离开公司。 |
A命令 |
A_k |
把每位员工的工资加上k |
S命令 |
S_k |
把每位员工的工资扣除k |
F命令 |
F_k |
查询第k多的工资 |
_(下划线)表示一个空格,I命令、A命令、S命令中的k是一个非负整数,F命令中的k是一个正整数。
在初始时,可以认为公司里一个员工也没有。
【输出文件】
输出文件的行数为F命令的条数加一。
对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1。
输出文件的最后一行包含一个整数,为离开公司的员工的总数。
【样例输入】
I
I
S
F
I
S
A
F
F
【样例输出】
-
【约定】
l I命令的条数不超过100000
l A命令和S命令的总条数不超过100
l F命令的条数不超过100000
l 每次工资调整的调整量不超过1000
l 新员工的工资不超过100000
【题意】
要求设计一种数据结构,能够快速进行以上4种操作,完成对整个工资单的动态维护。
【分析】
这种动态问题,很明显的要用到动态的数据结构来维护,可以使用一般的线段树或者平衡树进行解决,而本题的特点非常适合Splay的发挥。
首先是看到A和S命令,都是针对整个工资单中的所有员工进行操作的,因此可以考虑不改变每个员工单独的值(n个员工就要改n次,开玩笑......),而是用另外一个独立的变量把所有的加减操作都记录下来,判断员工出局的时候再结合题目给定的最低值计算出下限。这里要注意的是,但是当一个员工新加入时,之前的调工资操作应该对他是不产生影响的,因为那时候这个人还不在,但是用来记录工资加减的独立变量只有一个,所以在新员工加入的时候要把之前的工资加减情况减掉,这样最后计算时才可以把前面的部分抵消掉。
另,若一个人的初始工资小于底线,则这个人的离开不算到最后的答案中。
插入和找第k值都是基本的二叉树很容易解决,删除操作是本题的重点:
测试模板和修改删除部分花了大把的时间..T_T
根据上面的思路,用mi表示给定的底线,tot记录工资加减情况,则最后mi-tot就是初始工资的相对底线,每次出现S,也就是减了工资之后,就需要把树中低于mi-tot的所有值都删掉。但是splay在实际使用过程中,若树中存在多个mi-tot的值,则由于中间有各种旋转、splay操作,直接查找mi-tot得到的位置不能够确定剩下的是在左子树还是右子树还是两个都有。于是采取的方案:
1.搜索mi-tot-1
2.若不存在,则插入一个mi-tot-1,将其旋转到根,然后把根和左子树都删掉!!!树中剩下的就是大于mi-tot-1,也就是大于等于mi-tot的值了,注意计数时不要忘记这个根是自己加进去的,不要算进去。
3.若存在mi-tot-1,则同样将根和左子树都删掉,然后在右子树中搜索mi-tot-1,旋转到根删掉,不断重复直到整棵树中不存在mi-tot-1
/* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : cashier
************************************************ */ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; #define MAXN 100010 int sons[MAXN][];
int father[MAXN],size[MAXN],data[MAXN];
int spt=,spttail=,tot=,men=; void rotate(int x,int w) //rotate(node,0/1)
{
int y=father[x];
sons[y][-w]=sons[x][w];
if (sons[x][w]) father[sons[x][w]]=y; father[x]=father[y];
if (father[y])
if (y==sons[father[y]][]) sons[father[y]][]=x;
else sons[father[y]][]=x; sons[x][w]=y;
father[y]=x; size[x]=size[y];
size[y]=size[sons[y][]]+size[sons[y][]]+;
} void splay(int x,int y) //splay(node,position)
{
if (!x) return ;
while(father[x]!=y)
{
if (father[father[x]]==y)
if (x==sons[father[x]][]) rotate(x,);
else rotate(x,);
else
if (father[x]==sons[father[father[x]]][])
if (x==sons[father[x]][])
{
rotate(father[x],);
rotate(x,);
} else
{
rotate(x,);
rotate(x,);
}
else
if (x==sons[father[x]][])
{
rotate(father[x],);
rotate(x,);
} else
{
rotate(x,);
rotate(x,);
}
}
if (!y) spt=x;
} void search(int x,int w)
{
while(data[x]!=w)
{
if (w<data[x])
{
if (sons[x][]) x=sons[x][];
else break;
} else if (w>data[x])
{
if (sons[x][]) x=sons[x][];
else break;
}
}
splay(x,);
} void insert(int w) //insert(value)
{
spttail++;
data[spttail]=w;
size[spttail]=;
sons[spttail][]=;
sons[spttail][]=;
if (!spt)
{
father[spttail]=;
spt=spttail;
} else
{
int x=spt;
while()
{
size[x]++;
if (w<data[x])
if (sons[x][]) x=sons[x][];
else break;
else
if (sons[x][]) x=sons[x][];
else break;
}
father[spttail]=x;
if (w<data[x]) sons[x][]=spttail;
else sons[x][]=spttail;
splay(spttail,);
}
} void select(int x,int v) //select(root,k)
{
while(v!=size[sons[x][]]+)
{
if (v<=size[sons[x][]]) x=sons[x][];
else
{
v-=size[sons[x][]]+;
x=sons[x][];
}
}
splay(x,);
} int main()
{
freopen("cashier.in","r",stdin);
freopen("cashier.out","w",stdout); int n,mi;
scanf("%d%d",&n,&mi); spt=;
spttail=;
tot=;
men=; for (int i=;i<=n;i++)
{
char c;
c=getchar();
while(c!='I'&&c!='A'&&c!='S'&&c!='F') c=getchar();
int k;
scanf("%d",&k); if (c=='I')
{
if (k>=mi) insert(k-tot);
} else
if (c=='A')
{
tot+=k;
} else
if (c=='S')
{
tot-=k; search(spt,mi-tot-);
if (data[spt]!=mi-tot-)
{
insert(mi-tot-);
men+=size[sons[spt][]];
spt=sons[spt][];
father[spt]=;
} else
{
men+=size[sons[spt][]]+;
spt=sons[spt][];
father[spt]=;
search(spt,mi-tot-);
while(data[spt]==mi-tot-)
{
men++;
spt=sons[spt][];
father[spt]=;
search(spt,mi-tot-);
}
}
} else
{
if (k>size[spt]) printf("-1\n");
else
{
select(spt,size[spt]-k+);
printf("%d\n",data[spt]+tot);
}
} //printf("Size:%d mi-tot+1:%d\n",size[spt],mi-tot); //debug
} //printf("%d\n",men-size[spt]);
printf("%d\n",men); return ;
}
NOI2004 郁闷的出纳员 Splay的更多相关文章
- BZOJ 1503: [NOI2004]郁闷的出纳员 splay
1503: [NOI2004]郁闷的出纳员 Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作 ...
- 【BZOJ1503】 [NOI2004]郁闷的出纳员 splay
splay模板题,都快把我做忧郁了. 由于自己调两个坑点. 1.删除时及时updata 2.Kth 考虑k满足该点的条件即r->ch[1]->size+1<=k && ...
- 洛谷P1486 [NOI2004]郁闷的出纳员(splay)
题目描述 OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资 ...
- BZOJ1503 [NOI2004]郁闷的出纳员 splay
原文链接http://www.cnblogs.com/zhouzhendong/p/8086240.html 题目传送门 - BZOJ1503 题意概括 如果某一个员工的工资低于了min,那么,他会立 ...
- 洛谷.1486.[NOI2004]郁闷的出纳员(Splay)
题目链接 /* BZOJ1503: 3164kb 792ms/824ms(新建节点) 洛谷 : 3.06mb 320ms/308ms(前一个要慢wtf 其实都差不多,但前者好写) 四种操作: A:所有 ...
- bzoj1503[NOI2004]郁闷的出纳员——Splay
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1503 好奇怪呀!为什么而TLE? 各种修改终于卡时过了.可是大家比我快多了呀?难道是因为自己 ...
- BZOJ[NOI2004]郁闷的出纳员 | Splay板子题
题目: 洛谷也能评测....还有我wa了10多次的记录233 题解: 不要想得太复杂,搞一个全局变量记录一下工资的改变量Delta,这样可以等询问的时候就输出val+Delta,然后插入的时候插入x- ...
- BZOJ_1503 [NOI2004]郁闷的出纳员 【Splay树】
一 题面 [NOI2004]郁闷的出纳员 二 分析 模板题. 对于全部员工的涨工资和跌工资,可以设一个变量存储起来,然后在进行删除时,利用伸展树能把结点旋转到根的特性,能够很方便的删除那些不符合值的点 ...
- BZOJ 1503: [NOI2004]郁闷的出纳员
1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 10526 Solved: 3685[Submit][Stat ...
随机推荐
- mvc UrlHelper
何谓Helper,其实就是在View中为了实现一些灵活功能而写的方法组. 其实ASP.NET MVC的View是Aspx的页面,本身可以声明定义方法,那为什么要有Helper呢? 其实无非是将界面与逻 ...
- Mysql:输出到文件
mysql>tee /home/a.txt mysql>show processlist; mysql>exit tee命令能重定向输出,同时屏幕会同步显示.
- docker 基础命令二
开启/停止/重启 查看当前正在运行容器docker ps 查看包括已经停止的所有容器docker ps -a 显示最新启动的一个容器docker ps -l 新建一个容器运行docker run 启动 ...
- flex超链接
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="ht ...
- Glusterfs 分布式存储安装部署
Glusterfs 分布式存储部署 是存储当中可以选择的一种 现在很多虚拟化 云计算都在用软件存储 例如 ceph Glusterfs 等等 今天我们部署一下Glusterfs环境 GlusterFs ...
- Css 之 px em %
在页面整体布局中,页面元素的尺寸大小(长度.宽度.内外边距等)和页面字体的大小也是重要的工作之一.一个合理设置,则会让页面看起来层次分明,重点鲜明,赏心悦目.反之,一个不友好的页面尺寸和字体大小设置, ...
- Debian 安装Nvidia显卡驱动
1.到nvidia官方网站下载自己显卡对应型号得驱动,如果不知道显卡型号,可以使用如下命令来查看 lspci | grep VGA 2.安装显卡驱动所必需得工具 apt-get install bui ...
- Debian下VIM的安装和配置
1.安装 apt-get install vim 2.配置 这是我的vim 配饰文件,基本的功能都能实现,在这里做一个备份,省的以后重装系统还要到处找这个配置文件(/etc/vim/vimrc) : ...
- Loadrunner之脚本的调试和保存(六)
一.调试脚本 脚本录制完毕后,按F5键或单击菜单上的RUN按钮,可以运行脚本. 在VIRTUAL USER GENERATOR中运行脚本的作用,主要是查看录制的脚本能否正常通过,如果有问题 ...
- 4D(DRG、DLG、DOM、DEM)数据 概念
抱歉原文链接未知 Technorati 标签: DRG,DLG,DOM,DEM 以下有不同的说法,但是意思都很相近. 一. DOM (数字正射影像图):利用数字高程模型对扫描处理的数字化的航空相片.遥 ...