ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

950. 郁闷的出纳员

2022-07-09 03:04:18  阅读:158  来源: 互联网

标签:int 950 出纳员 tr splay 命令 郁闷 工资 员工


题目链接

950. 郁闷的出纳员

OIER 公司是一家大型专业化软件公司,有着数以万计的员工。

作为一名出纳员,我的任务之一便是统计每位员工的工资。

这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。

如果他心情好,就可能把每位员工的工资加上一个相同的量。

反之,如果心情不好,就可能把他们的工资扣除一个相同的量。

我真不知道除了调工资他还做什么其它事情。

工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。

每位员工的工资下界都是统一规定的。

每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。

老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第 \(k\) 多的员工拿多少工资。

每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。

好了,现在你已经对我的工作了解不少了。

正如你猜的那样,我想请你编一个工资统计程序。

怎么样,不是很困难吧?

输入格式

第一行有两个非负整数 \(n\) 和 \(min\),\(n\) 表示下面有多少条命令,\(min\) 表示工资下界。

接下来的 \(n\) 行,每行表示一条命令,命令可以是以下四种之一:

  1. I 命令,格式为 I_k,表示新建一个工资档案,初始工资为 \(k\)。如果某员工的初始工资低于工资下界,他将立刻离开公司。
  2. A 命令,格式为 A_k,表示把每位员工的工资加上 \(k\)。
  3. S 命令,格式为 S_k,表示把每位员工的工资扣除 \(k\)。
  4. F 命令,格式为 F_k,表示查询第 \(k\) 多的工资。

_(下划线)表示一个空格,I 命令、A 命令、S 命令中的 \(k\) 是一个非负整数,F 命令中的 \(k\) 是一个正整数。

在初始时,可以认为公司里一个员工也没有。

输出格式

输出行数为 \(F\) 命令的条数加一。

对于每条 \(F\) 命令,你的程序要输出一行,仅包含一个整数,为当前工资第 \(k\) 多的员工所拿的工资数,如果 \(k\) 大于目前员工的数目,则输出 \(-1\)。

输出文件的最后一行包含一个整数,为离开公司的员工的总数。

注意,如果某个员工的初始工资低于最低工资标准,那么将不计入最后的答案内。

数据范围

I 命令的条数不超过 \(10^5\),
A 命令和 S 命令的总条数不超过 \(100\),
F 命令的条数不超过 \(10^5\),
每次工资调整的调整量不超过 \(1000\),
新员工的工资不超过 \(10^5\)。

输入样例:

9 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2

输出样例:

10
20
-1
2

解题思路

splay

由于每次插入一个数,都按照值在中序遍历中的位置插入,而所有的操作都不改变 \(splay\) 所维护的中序遍历的顺序,所以整个操作中 \(splay\) 维护的中序遍历的值是有序的,而本题关键在于删除一个区间,删除一个区间往往引入两个哨兵 \(-inf,inf\),其中 \(L\) 表示值为 \(-inf\) 的节点,不妨用 \(d\) 记下目前增减操作的值,而每次删除节点时,要求删除的节点表示的值 \(x\),满足 \(inf<x+d<mn\),则需删除 \(splay\) 中表示值为 \([0,mn-d)\) 的节点,则需将这些节点放在一棵子树上便于删除,则需找到最小满足 \(x\geq mn-d\) 的 \(x\) 的代表的节点 \(R\),然后有两种方法将所求区间变为一棵子树:1. \(splay(R,0),splay(L,R)\),此时 \(L\) 的右子树即为所求;2. \(splay(L,0),splay(R,L)\),此时 \(R\) 的左子树即为所求

  • 时间复杂度:\(O(nlogn)\)

代码

// Problem: 郁闷的出纳员
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/952/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=1e5+5,inf=1e8;
int root,cnt,d,n,mn,k,res;
struct Tr
{
	int s[2],sz,p,v;
	void init(int _p,int _v)
	{
		p=_p,v=_v;
	}
}tr[N];
void pushup(int u)
{
	tr[u].sz=tr[tr[u].s[0]].sz+tr[tr[u].s[1]].sz+1;
}
void rotate(int x)
{
	int y=tr[x].p,z=tr[y].p;
	int k=tr[y].s[1]==x;
	tr[z].s[tr[z].s[1]==y]=x,tr[x].p=z;
	tr[y].s[k]=tr[x].s[k^1],tr[tr[x].s[k^1]].p=y;
	tr[x].s[k^1]=y,tr[y].p=x;
	pushup(y),pushup(x);
}
void splay(int x,int k)
{
	while(tr[x].p!=k)
	{
		int y=tr[x].p,z=tr[y].p;
		if(z!=k)
		{
			if((tr[z].s[1]==y)^(tr[y].s[1]==x))rotate(x);
			else
				rotate(y);
		}
		rotate(x);
	}
	if(!k)root=x;
}
int insert(int v)
{
	int u=root,p=0;
	while(u)p=u,u=tr[u].s[v>tr[u].v];
	u=++cnt;
	if(p)tr[p].s[v>tr[p].v]=u;
	tr[u].init(p,v);
	splay(u,0);
	return u;
}
int find(int val)
{
	int u=root,res=-1;
	while(u)
	{
		if(tr[u].v>=val)res=u,u=tr[u].s[0];
		else
			u=tr[u].s[1];
	}
	return res;
}
int get_k(int k)
{
	int u=root;
	while(u)
	{
		if(tr[tr[u].s[0]].sz>=k)u=tr[u].s[0];
		else if(tr[tr[u].s[0]].sz+1==k)return tr[u].v;
		else
			k-=tr[tr[u].s[0]].sz+1,u=tr[u].s[1];
	}
	return -1;
}
int main()
{
    scanf("%d%d",&n,&mn);
    int L=insert(-inf),R=insert(inf);
    while(n--)
    {
    	char op[2];
    	scanf("%s%d",op,&k);
    	if(*op=='I')
    	{
    		if(k>=mn)insert(k-d),res++;
    	}
    	else if(*op=='A')d+=k;
    	else if(*op=='S')
    	{
    		d-=k;
    		int R=find(mn-d);
    // 		splay(R,0),splay(L,R);
    // 		tr[L].s[1]=0;
    // 		pushup(R),pushup(L);
    		splay(R,0),splay(L,R);
    		tr[L].s[1]=0;
    		pushup(L),pushup(R);
    	}
    	else
    	{
    		if(tr[root].sz-2<k)puts("-1");
    		else
    			printf("%d\n",get_k(tr[root].sz-k)+d);
    	}
    }
    printf("%d",res+2-tr[root].sz);
    return 0;
}

标签:int,950,出纳员,tr,splay,命令,郁闷,工资,员工
来源: https://www.cnblogs.com/zyyun/p/16460015.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有