题目比较简单,用splay动态维护一个可以整体删除的集合,
不需要打下标,打个上标维护size求kth,
用delta记录偏移即可完成所有操作。
调试了两个小时,后来发现因初始工资而走的员工不能算是走的员工,题目中没说明,太坑了。
在splay中,常用INF哨兵,但我没发现有人用null哨兵,我发现null哨兵能够大幅简化代码,同时具有一定的容错性。
程序的容错性非常重要,即使参数正常也最好写个指针检查,不要在乎这点常数,当访问到null甚至是NULL的时候做特殊处理,即使不可能出现这种情况,在很多情况下也能救你一命。
如果我的Splay代码还有可以优化的地方请联系我!!
不需要打下标,打个上标维护size求kth,
用delta记录偏移即可完成所有操作。
调试了两个小时,后来发现因初始工资而走的员工不能算是走的员工,题目中没说明,太坑了。
在splay中,常用INF哨兵,但我没发现有人用null哨兵,我发现null哨兵能够大幅简化代码,同时具有一定的容错性。
程序的容错性非常重要,即使参数正常也最好写个指针检查,不要在乎这点常数,当访问到null甚至是NULL的时候做特殊处理,即使不可能出现这种情况,在很多情况下也能救你一命。
如果我的Splay代码还有可以优化的地方请联系我!!
#include <cstdio>
#include <cstdlib>
#include <climits>
using namespace std;
#define INF (INT_MAX/2)
struct Node {
int val,size,mul;
Node *ch[2],*father;
Node(int _val,int _mul,Node *_null):val(_val),size(_mul),mul(_mul) {
ch[0]=ch[1]=father=_null;
}
void setch(int w,Node *v) {
ch[w]=v;
v->father=this;
}
void rot() {
Node *u=father;
int w=(u->ch[0]==this);
u->setch(!w,ch[w]);
u->father->setch(u->father->ch[1]==u,this);
setch(w,u);
u->size=u->ch[0]->size+u->ch[1]->size+u->mul;
}
} *null=new Node(0,0,(Node*)0);
Node *root=null;
void splay(Node *v,Node *goodfather)
{
for(Node *u;(u=v->father)!=goodfather;v->rot())
if(u->father!=goodfather)
(((u->ch[0]==v)==(u->father->ch[0]==u->father))?u:v)->rot();
v->size=v->ch[0]->size+v->ch[1]->size+v->mul;
if(goodfather==null) root=v;
}
Node *S_lower(int x)
{
Node *ans=null;
for(Node *u=root;u!=null;u=u->ch[u->val<x]) {
if(u->val==x) return u;
if(u->val>x) ans=u;
}
return ans;
}
Node *S_upper(int x)
{
Node *ans=null;
for(Node *u=root;u!=null;u=u->ch[u->val<x]) {
if(u->val==x) return u;
if(u->val<x) ans=u;
}
return ans;
}
void s_insert(int goodval)
{
if(root==null) {root=new Node(goodval,1,null);return;}
Node *res=null,*u=root;
while(true) {
int w=u->val<goodval;
if(u->val==goodval) {
++(res=u)->mul;
break;
} else if(u->ch[w]==null) {
u->setch(w,res=new Node(goodval,1,null));
break;
} else u=u->ch[w];
}
splay(res,null);
}
int s_delete(int l,int r)
{
splay(S_upper(l),null);
splay(S_lower(r),root);
Node *seg=root->ch[1]->ch[0];
if(seg==null) return 0;
root->ch[1]->ch[0]=null;
(root->ch[1])->size=(root->ch[1])->ch[0]->size+(root->ch[1])->ch[1]->size+(root->ch[1])->mul;
root->size=root->ch[0]->size+root->ch[1]->size+root->mul;
return seg->size;
}
Node *s_kth(int k)
{
if(k<1) return null;
Node *u=root;
while(k<=u->size) {
int q1=u->ch[0]->size,q2=q1+u->mul;
if(k<=q1) u=u->ch[0];
else if(k>q2) {k-=q2;u=u->ch[1];}
else {splay(u,null);return u;}
}
return null;
}
int main()
{
int case_cnt,minval,num_go=0,delta=0;
scanf("%d%d",&case_cnt,&minval);
s_insert(-INF);s_insert(INF);
while(case_cnt--) {
char cmd[6];
int k;
scanf("%s%d",cmd,&k);
if(cmd[0]=='I') {
k-=delta;
if(k<minval-delta) ;//++num_go;>o<怎么可以这样?!!!
else s_insert(k);
} else if(cmd[0]=='A') {
delta+=k;
} else if(cmd[0]=='S') {
delta-=k;
num_go+=s_delete(-INF,minval-delta);//!!!!!!
} else if(cmd[0]=='F') {
Node *v=s_kth(root->size-2-k+1+1);
if(v==null || v->val>=INF || v->val<=-INF) printf("-1\n");
else printf("%d\n",v->val+delta);
}
}
printf("%d\n",num_go);
return 0;
}