题目描述
分析
听说暴力能过 ,不敢打Treap/线段树。
很巧妙的一道题,第一次听说树状数组查询第k大/小的数。
定义树状数组为工资点上的人数,对于工资的整体增减可以通过设置变量p统一维护,这个是很关键的变量,处理工资的整体浮动。
因为数值变化在正负数之间,而树状数组下标必须从1开始,因此要对所有工资值进行坐标平移,也就是
定义数轴原点dt=200000。
整体加工资,直接加到p值里;新员工入职用update 进行单点插入处理;
比较麻烦的是如何高效的处理减工资产生的离职和查询第k高收入。
先处理第k高收入的工资值查询,对于这个查询其实可以反过来看,如果当前在职总人数为cnt,则第k高
工资等价于第cnt-k+1小的工资,由树状数组的构造方式可以知道统计这个前缀值可以查询比他小的数,这个前cnt-k+1可以看作前缀和,设为s,可以使用倍增法快速逼近。
对于离职人员的处理,我们每次取出最低工资的人判断是否要离职(如果不用后面都不用),离职的人只需要将s这个工资点的人全部删掉(加上-c[s])。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,mn,leave,tot;
int dt=2e5,p;
long long c[400010];
int lowbit(int x)