(题解)(Splay)NOI2004郁闷的出纳员

来源:互联网 发布:js内置对象有哪些 编辑:程序博客网 时间:2024/06/05 21:57
题目比较简单,用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;}


0 0
原创粉丝点击