#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <iostream>
using namespace std;
//const int MAXN = 1e5 + 5;
int n, minn;
int cnt;
struct Splay {
struct Node {
Node *fa, *ch[2], **root;
int size, cnt, x;
Node(Node **root, Node *fa, int x) : root(root), fa(fa), x(x), size(1), cnt(1)
{
ch[0] = ch[1] = NULL;
}
int relation()
{
return this == fa->ch[1] ? 1 : 0;
}
void maintain()
{
size = cnt;
if (ch[1]) size += ch[1]->size;
if (ch[0]) size += ch[0]->size;
}
void rotate()
{
Node *old = fa;
int r = relation();
fa = old->fa;
if (old->fa)
{
old->fa->ch[old->relation()] = this;
}
if (ch[r ^ 1])
{
ch[r ^ 1]->fa = old;
}
old->ch[r] = ch[r ^ 1];
old->fa = this;
ch[r ^ 1] = old;
old->maintain();
maintain();
if (!fa)
{
*root = this;
}
}
void splay(Node *target = NULL)
{
while (fa != target)
{
if (fa->fa == target)
{
rotate();
}
else if (relation() == fa->relation())
{
fa->rotate();
rotate();
}
else
{
rotate();
rotate();
}
}
}
Node *pred()
{
//求前驱和后继之前必须是根
this->splay();
Node *v = ch[0];
while (v->ch[1]) v = v->ch[1];
return v;
}
Node *succ()
{
this->splay();
Node *v = ch[1];
while (v->ch[0]) v = v->ch[0];
return v;
}
int rank()
{
return ch[0] ? ch[0]->size : 0;
}
} *root;
Splay() : root(NULL)
{
insert(INT_MAX);
insert(INT_MIN);
}
Node *insert(int x)
{
Node **v = &root, *fa = NULL;
while ((*v) != NULL && (*v)->x != x)
{
fa = *v;
fa->size++;
if (x < fa->x)
{
v = &fa->ch[0];
}
else
{
v = &fa->ch[1];
}
}
if ((*v) != NULL)
{
(*v)->cnt++;
(*v)->size++;
}
else
{
(*v) = new Node(&root, fa, x);
}
(*v)->splay();
return root;
}
Node *find(int x)
{
Node *v = root;
while (v != NULL && v->x != x)
{
if (x < v->x)
{
v = v->ch[0];
}
else
{
v = v->ch[1];
}
}
if (v) v->splay();
return v;
}
// void erase(Node *v)
// {
// Node *pred = v->pred(), *succ = v->succ();
// pred->splay();
// succ->splay(pred);
//
// if (v->cnt > 1)
// {
// v->size--;
// v->cnt--;
// }
// else
// {
// delete succ->ch[0];
// succ->ch[0] = NULL;
// }
//
// succ->size--;
// pred->size--;
// }
//
// void erase(int x)
// {
// Node *v = find(x);
//
// if (!v) return;
// erase(v);
// }
// int rank(int x)
// {
// Node *v = find(x);
//
// if (v == NULL)
// {
// v = insert(x);
// int res = v->rank();
// erase(v);
// return res;
// }
// else
// {
// return v->rank();
// }
// }
int kth(int k)
{
Node *v = root;
while (!(k >= v->rank() && k < v->rank() + v->cnt))
{
if (k < v->rank())
{
v = v->ch[0];
}
else
{
k -= v->rank() + v->cnt;
v = v->ch[1];
}
}
v->splay();
return v->x;
}
// void add(int k, Node *v)
// {
// v->x += k;
// if (v->ch[0]) add(k, v->ch[0]);
// if (v->ch[1]) add(k, v->ch[1]);
// }
void erase(Node *l, Node *r)//删除区间
{
Node *pred = l->pred(), *succ = r->succ();
pred->splay();
succ->splay(pred);
delete succ->ch[0];
succ->ch[0] = NULL;
succ->maintain();
pred->maintain();
}
void kill(int l, int r)
{
Node *vl = find(l), *vr = find(r);
if (!vl) vl = insert(l);
if (!vr) vr = insert(r);
erase(vl, vr);
// while (v->ch[1]->x < minn)
// {
// v = v->ch[1];
// }
//
// v->splay();
// cnt += v->rank();
// v = v->ch[0];
//
// while (v->ch[0] || v->ch[1])
// {
// if (v->ch[0]) erase(v->ch[0]);
// if (v->ch[1]) erase(v->ch[1]);
// }
//
// // if (v->x < minn)
// // {
// // if (v->)
// // erase(v);
// // }
// //
}
int size()
{
return root->size - 2;
}
} splay;
int main()
{
int add = 0;
scanf("%d %d", &n, &minn);
for (int i = 0; i < n; i++)
{
//char fu;
int k;
//cin >> fu >> k;
//scanf("%c %d", &fu, &k);
// scanf("%c", &fu);
// scanf("%d", &k);
//这里为什么不能用scanf?
char s[2];
scanf("%s %d", s, &k);
if (s[0] == 'I')
{
// if (k < minn)
// {
// cnt++;
// }
if (k >= minn)
{
k -= add;
splay.insert(k);
}
// splay.insert(k);
// if (splay.find(k)->x < minn)
// {
// splay.erase(k);
// }
}
else if (s[0] == 'A')
{
add += k;
//splay.add(k, splay.root);
}
else if (s[0] == 'S')
{
add -= k;
//splay.add(-k, splay.root);
//splay.kill(splay.root);
int L = minn;
L -= add;
//int oldSize = splay.root->size - 2;
int oldSize = splay.size();
splay.kill(INT_MIN + 1, L - 1);
cnt += oldSize - splay.size();
}
else if (s[0] == 'F')
{
if (k > splay.root->size - 2 || k < 1)
{
printf("-1\n");
}
else
{
printf("%d\n", splay.kth((splay.root->size - 2) - k + 1) + add);
}
}
}
printf("%d\n", cnt);
return 0;
}
抄了sulfur6【团长的博客!】和Menci两位神犇的代码【也就是说基本上没有我自己写的,我把代码放这主要是想写一些错误啥的!】。感谢!
这道题调的我已经变身郁闷的程序员了好吗qnq
那一条条来说一下我的心(zhi)路(zhang)历程
1)Splay里的while老写成if
2)区间删除我写的奇奇怪怪【就是不会写然后xjb写】最后区间删除的做法和删一个点思想一样,不同的就是是把那个区间而不是一个点转过去【好像有一种把一个区间缩成点的意思?】然后传进去的参数是两个数字,这样很方便。
3)我加工资和减工资一开始都是写的递归下去全改了,然后就是段错误。【我改成打标记就没有段错误了,可能是我递归也写错了吧】【我每次调Splay都会在求前驱和后继那里段错误!每次都会!话说求前驱和后继需要转到根?这个程序里可能在什么我不知道的地方转过去了吧(挠头)我再好好看看(唉还是有不懂的地方啊qnq一知半解的。。。。。)】这是在全局打标记,团长说Menci的是在Splay里打标记 ,我去学!
4)然后减工资踢人的时候就要加上标记的相反数。我一开始想工资下限又没有变,为什么要改?这样想,他们的工资全涨了一个数,但实际上只是标记了一下,没有给他们实际改工资,那这样的话工资下限以下的人要被踢掉【哦不,是辞职】但是按原先的工资下限的话肯定不行,因为这样涨工资之后实际上在工资下限以上的人也会被踢【就这样说吧owo】那就让工资下限降低,他们应该涨多少就工资下限就降多少【就相当于相对运动?你往东走就相当于我往西走这样】BINGO!问题解决!,时间从每次O(n)变成了O(1)【好像是这样,时间复杂度我还不是很会算qnq(托腮)】还有查询的时候要加上标记。
5)改成了和团长的代码差不多一样之后还是过不了样例。把scanf改成cin之后好了很多!(还是过不了。。。)这里我不懂,问了Menci。说是因为scanf(“%c”)会把’\n’和’\0’也读进去(大坑啊)【话说还有两个大坑,知乎回答里说的,if (x = 0) die Gavin;
(hhhhhh顺手黑栋栋(别打我,逃))和int a, b; long long c = a * b;
(然而还是逃脱不了爆int的命运(逃))】Fancy学姐的解决方法是每次读一个字符串(超强!)。开一个char s[2]
用的时候取s[0]就行【这里是char s[数组内的元素个数]
,我还以为开char s[1]
,然后s[0]存字符,s[1]存’\0’就行呢qnq然而事实根本不是我想象的那样(摊手)我果真naive】
6)可是被踢出去的人数还是统计错了,我把求树的大小从每次求改成写在Splay的函数里不知道为什么就对了,我觉得并没有什么区别啊【回来仔细研究系列。。。。】
唉,可是不易= =我一个抄板子都抄不对的废人。。。。。