题解
使用权值线段树解决问题
记录一个mdf表示先前工资的变动 增加工资时增加mdf减少工资时减少mdf并将工资小于min - mdf - 1的数值标记清除 每次查询第k大先判断是否有足够人数
使用一个tot记录加入人数 最后使用tot-线段树1节点的人数即为离开人数
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 4e5 + 10;
struct node
{
int l, r, v, lzy;
void Lazy()
{
v = 0;
lzy = 1; //区间清零
}
}tre[MAXN * 4];
inline void PushUp(int x)
{
tre[x].v = tre[x << 1].v + tre[x << 1 | 1].v;
}
inline void PushDown(int x)
{
if (tre[x].lzy)
{
tre[x << 1].Lazy(), tre[x << 1 | 1].Lazy();
tre[x].lzy = 0;
}
}
void Build(int x, int l, int r)
{
tre[x].l = l, tre[x].r = r, tre[x].v = tre[x].lzy = 0;
if (l == r)
return;
int m = l + r >> 1;
Build(x << 1, l, m);
Build(x << 1 | 1, m + 1, r);
}
void Update(int x, int v, int k) //将值v增加k个 单点修改
{
int l = tre[x].l, r = tre[x].r;
if (l == r)
{
tre[x].v += k;
return;
}
PushDown(x);
int m = l + r >> 1;
if (v <= m)
Update(x << 1, v, k);
else
Update(x << 1 | 1, v, k);
PushUp(x);
}
void Erase(int x, int pl, int pr) //将值[pl, pr]清零 区间修改lzy标记
{
int l = tre[x].l, r = tre[x].r;
if (pl <= l && r <= pr)
{
tre[x].Lazy(); //因为lazy不能记录清空数量
return;
}
PushDown(x);
int m = l + r >> 1;
if (m >= pl)
Erase(x << 1, pl, pr);
if (m < pr)
Erase(x << 1 | 1, pl, pr);
PushUp(x);
}
int Kth(int x, int k) //返回全局倒数第k大的值 其它功能见非区间清零
{
int l = tre[x].l, r = tre[x].r;
if (l == r)
return l; //L
int m = l + r >> 1;
if (tre[x << 1 | 1].v >= k) //倒数正数切换左右侧
return Kth(x << 1 | 1, k);
return Kth(x << 1, k - tre[x << 1 | 1].v);
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int N, mi;
cin >> N >> mi;
Build(1, -2e5, 2e5);
int mdf = 0, tot = 0, v; //整体修改值 人数
char op[10];
for (int i = 1; i <= N; i++)
{
scanf("%s%d", op, &v);
if (op[0] == 'I' && v >= mi)
Update(1, v - mdf, 1), tot++;
else if (op[0] == 'A')
mdf += v;
else if (op[0] == 'S')
{
mdf -= v;
if (mi - mdf - 1 >= -2e5)
Erase(1, -2e5, mi - mdf - 1);
}
else if (op[0] == 'F')
{
if (v > tre[1].v) //超过总人数
printf("-1\n");
else
printf("%d\n", Kth(1, v) + mdf);
}
}
cout << tot - tre[1].v << endl;
return 0;
}