OIER 公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。
工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。
老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。
好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?
如果某个员工的初始工资低于最低工资标准,那么将不计入最后的答案内。
第一行有两个非负整数 \(n\) 和 \(\min\)。\(n\) 表示下面有多少条命令,\(\min\) 表示工资下界。
接下来的 \(n\) 行,每行表示一条命令。命令可以是以下四种之一:
\(\texttt{F k}\) 查询第 \(k\) 多的工资。
输出文件的行数为 \(F\) 命令的条数加一。
对于每条 \(F\) 命令,你的程序要输出一行,仅包含一个整数,为当前工资第 \(k\) 多的员工所拿的工资数,如果 \(k\) 大于目前员工的数目,则输出 \(-1\)。
输出文件的最后一行包含一个整数,为离开公司的员工的总数。
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\) 的操作,预见我的学习笔记
谨慎学 \(splay\) ,温馨提示,
上网学 \(splay\) ,风险特别多。
一份好博客,省你一天劳!
因为网上“极好”的博客,使我对着一份代码折腾了自己一天
好,因为是模板题,所以对每个操作说明一下就好了
对于 \(\texttt{I k}\) ,把它当成 \(Insert\) 操作,把 \(\geq min\) 的工资插入即可
对于 \(\texttt{A k}\) 和 \(\texttt{S k}\),暴力加或减即可。
对于 \(\texttt{F k}\),那就查询第 \(k\) 大好了
然而,减数后,有些人将被淘汰
所以我想了一个 \(leave\) 操作
把 \(\min-1\) 的后继旋转到根,左子树都比跟小,因为根 \(\geq min\) 所以左子树都将被淘汰,删去即可
但要查后继,万一没有后继岂不就 \(gg\) 了吗?
所以插入一个极大值
珍惜生命,注意细节!
#include<cstdio>
using namespace std;
const int N = 1e5 , INF = 1e9;
int n , min , k , root , tot , sum;
char opt;
struct tree{
int ch[2] , size , val , cnt , fa;
}t[N + 5];
inline int read()
{
register char ch = getchar();
register int res = 0;
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') res = res * 10 + ch - '0' , ch = getchar();
return res;
}
inline void update(int x)
{
t[x].size = t[t[x].ch[0]].size + t[t[x].ch[1]].size + t[x].cnt;
}
inline void rotate(int x)
{
register int y = t[x].fa , z = t[y].fa , k = t[y].ch[1] == x;
t[z].ch[t[z].ch[1] == y] = x , t[x].fa = z;
t[y].ch[k] = t[x].ch[k ^ 1] , t[t[x].ch[k ^ 1]].fa = y;
t[x].ch[k ^ 1] = y , t[y].fa = x;
update(y) , update(x);
}
inline void splay(int x , int goal)
{
while (t[x].fa != goal)
{
int y = t[x].fa , z = t[y].fa;
if (z != goal) (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y);
rotate(x);
}
if (goal == 0) root = x;
}
inline void insert(int x)
{
register int u = root , fa = 0;
while (u && t[u].val != x) fa = u , u = t[u].ch[x > t[u].val];
if (u) t[u].cnt++;
else
{
u = ++tot;
if (fa) t[fa].ch[x > t[fa].val] = u;
t[u].ch[1] = t[u].ch[0] = 0 , t[u].size = t[u].cnt = 1 , t[u].fa = fa , t[u].val = x;
}
splay(u , 0);
}
inline int kth(int x)
{
register int u = root;
if (t[u].size < x) return -1;
while (1)
{
register int y = t[u].ch[1];
if (x > t[y].size + t[u].cnt) x -= t[y].size + t[u].cnt , u = t[u].ch[0];
else
{
if (t[y].size >= x) u = y;
else return t[u].val;
}
}
}
inline void find(int x)
{
register int u = root;
if (!u) return;
while (t[u].ch[x > t[u].val] && x != t[u].val) u = t[u].ch[x > t[u].val];
splay(u , 0);
}
inline int Next(int x , int f)
{
find(x);
register int u = root;
if ((t[u].val > x && f) || (t[u].val < x && !f)) return u;
u = t[u].ch[f];
while (t[u].ch[f ^ 1] != 0) u = t[u].ch[f ^ 1];
return u;
}
inline int leave()
{
register int u = Next(min - 1 , 1);
splay(u , 0) , sum += t[t[u].ch[0]].size , t[u].ch[0] = 0 , update(u);
}
int main()
{
n = read() , min = read();
insert(INF);
for(register int i = 1; i <= n; i++)
{
opt = getchar();
while (opt != 'I' && opt != 'A' && opt != 'S' && opt != 'F') opt = getchar();
k = read();
if (opt == 'I' && k >= min) insert(k);
else if (opt == 'A')
for(register int j = 1; j <= tot; j++) t[j].val += k;
else if (opt == 'S')
{
for(register int j = 1; j <= tot; j++) t[j].val -= k;
leave();
}
else if (opt == 'F') printf("%d\n" , kth(k + 1));
}
printf("%d" , sum);
}
原文:https://www.cnblogs.com/leiyuanze/p/12188748.html