bzoj1503: [NOI2004]郁闷的出纳员

来源:互联网 发布:读mpacc的体验 知乎 编辑:程序博客网 时间:2024/06/05 09:57

做一个标记tag表示现在总的人员的change值

对于题目中的每一个操作我们可以用treap维护这个数列
1.I命令 加入一个k-tag的值
2.A命令 tag+k
3.S命令 tag-k,删除不合法的值
4.F命令 二分查k大

调了很久,注意读入

#include <cstdio>#include <ctype.h>#include <cstdlib>#define Magic 19260817template<typename T>T read(T &f){    f=0;    int x=1;    char c=getchar();    while(!isdigit(c)){if(c=='-')x=-1;c=getchar();}    while(isdigit(c))f=f*10+c-'0',c=getchar();    return f*x;}struct Node{    Node* ch[2];    int r;    int v;    int s;    Node (int v=0):v(v){        ch[0]=ch[1]=NULL;        s=1;        r=rand();    }    int cmp(int x)const{        if(x==v)            return -1;        else            return x < v ? 0 : 1;    }    void maintain(){        s=1;        if(ch[0]!=NULL)            s+=ch[0]->s;        if(ch[1]!=NULL)            s+=ch[1]->s;    }};void rotate(Node* &o,int d){    Node* k=o->ch[d^1];    o->ch[d^1]=k->ch[d];    k->ch[d]=o;    o->maintain();    k->maintain();    o=k;}void insert(Node* &o,int x){    if(o==NULL)        o=new Node(x);    else{        int d=(x < o->v ? 0 : 1);        insert(o->ch[d],x);        if(o->ch[d]->r > o->r)            rotate(o,d^1);    }    o->maintain();}Node* find(Node* &o,int x){    if(o==NULL)        return NULL;    if(o->v==x)        return o;    return (x < o->v ? find(o->ch[0],x) : find(o->ch[1],x));}int kth(Node* &o,int k){    if( o == NULL && k <= 0 && k > o->s )        return 0;    int s=(o->ch[0]==NULL ? 0 : o->ch[0]->s);    if(k==s+1)        return o->v;    else if(k<=s)        return kth(o->ch[0],k);    else        return kth(o->ch[1],k-s-1);}int n,Min;int Atg,top,ans;int v;char opt;void remove(Node* &o,int x){    if(o==NULL)        return;    if(o->v >= x)        remove(o->ch[0],x);    else{        if(o->ch[0]!=NULL)            ans+=o->ch[0]->s;        ans+=1;        o=o->ch[1];        remove(o,x);    }    if(o!=NULL)        o->maintain();}#define INF 1<<30Node* root;int main(){    srand(Magic);    read(n);    read(Min);    while(n--){        while (opt = getchar(), !(opt >= 'A' && opt <= 'Z'));        read(v);        if(opt=='I'){            if(v>=Min)                insert(root,v-Atg);        }        else if(opt=='A')            Atg+=v;        else if(opt=='S')            Atg-=v,remove(root,Min-Atg);        else if(opt=='F'){            if(root==NULL || v > root->s || v<=0)                printf("-1\n");            else                printf("%d\n",Atg+kth(root,root->s - v+1));        }    }    printf("%d\n",ans);    return 0;}