传送门
题目简述
维护一个数列,同时约定一个下界,当一个元素低于该下界时,将其删除。统计最终删去的数的个数
有以下操作:
1. 增加一个元素(若该元素低于下界,则无视该操作)
2. 将每一个元素加上一个数
3. 将每一个元素减去一个数
4. 查询第k大的数
分析
直接建树感觉是不可能的(整体操作绝对会Tle),因此,考虑从相对关系上对原数列进行处理。
既然是以下界(k)来判断,那么对于整体的加减操作,则可以转化为对k的减加操作。
对于删除节点,只需要在减工资后,将小于k的元素全部删除即可
代码
#include <cstdio>
#include <cstdlib>
#define IL inline
using namespace std;
IL int read()
{
int k = 1, sum = 0;
char c = getchar();
for(; '0' > c || c > '9'; c = getchar())
if(c == '-') k = -1;
for(; '0' <= c && c <= '9'; c = getchar())
sum = sum * 10 + c - '0';
return sum * k;
}
int tot;
struct node
{
node *father;
node *son[2];
int size;
int val;
int cnt;
IL node(int v = 0, node *f = 0)
{
father = f;
son[0] = son[1] = 0;
size = 1;
val = v;
cnt = 0;
}
};
node *root;
IL int size(node *p)
{
return p ? p->size : 0;
}
IL bool son(node *f, node *p)
{
return f ? (f->son[1] == p) : -1;
}
IL void connect(node *f, node *p, bool k)
{
if(!f) root = p; else f->son[k] = p;
if(p) p->father = f;
}
IL void updata(node *p)
{
p->size = size(p->son[0]) + size(p->son[1]) + p->cnt;
}
IL void rotate(node *p)
{
node *f = p->father, *g = f->father;
bool x = son(f, p), y = !x;
connect(f, p->son[y], x);
connect(g, p, son(g, f));
connect(p, f, y);
updata(f);
}
IL void splay(node *p, node *q)
{
for(node *f, *g; p->father != q;)
{
f = p->father;
g = f->father;
if(g == q) rotate(p); else
{
if(son(g, f) ^ son(f, p))
rotate(p), rotate(p);
else
rotate(f), rotate(p);
}
}
updata(p);
}
IL void insert(int val)
{
if(!root) root = new node(val, 0);
for(node *p = root; p; p = p->son[val > p->val])
{
if(p->val == val)
{
++(p->cnt);
splay(p, 0);
return ;
}else
if(!p->son[val > p->val])
p->son[val > p->val] = new node(val, p);
}
}
inline node *find_nxt(int val)
{
node *x = 0;
for(node *p = root; p; p = p->son[val > p->val])
if(p->val >= val)
x = p;
return x;
}
IL void earse_2(int val)
{
node *p = find_nxt(val);
if(!p)
{
tot += size(root);
root = 0;
}else
{
splay(p, 0);
tot += size(p->son[0]);
p->son[0] = 0;
updata(p);
}
}
IL int rankx(int t)
{
for(node *p = root; p;)
{
if(t <= size(p->son[0])) p = p->son[0]; else
if(t - size(p->son[0]) <= p->cnt)
{
splay(p, 0);
return p->val;
}else
{
t -= size(p->son[0]) + p->cnt;
p = p->son[1];
}
}
}
int main()
{
int n = read(), del = read();
char c;
for(int x, sum = 0; n; -- n)
{
scanf(" %c", &c);
x = read();
if(c == 'I')
{
x -= del; // 此处纯属好玩,本可以无视
if(x >= 0) insert(x + sum); // 注意先判断
}else
if(c == 'A')
{
sum -= x;
}else
if(c == 'S')
{
sum += x;
earse_2(sum);
}else
if(c == 'F')
{
if(size(root) < x) printf("-1\n"); else
printf("%d\n", rankx(size(root) - x + 1) - sum + del);
}
}
printf("%d\n", tot);
}