BZOJ 1503: [NOI2004]郁闷的出纳员 [treap]

传送门

题意:插入一个数,全体加,全体减,删除小于一个数的所有数,求$k$大


 

全局标记然后平衡树直接搞就行了

删除操作不断的找最小值然后删除复杂度是对的,然而$Candy?$这个沙茶找最小没有判$x==0$超时郁闷了好长时间....

或者你也可以乱搞一个$treap$的左子树删除...时间差了$50ms$左右

然后对于第一种做法潸然生日再次自带$50ms$常数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define lc t[x].l
#define rc t[x].r
const int N=1e5+5;
int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
int n,lim,all,v;
char s[5];
struct Node{
    int l,r,v,w,size,rnd;
}t[N];
int sz,root;
inline void update(int x){t[x].size=t[lc].size+t[rc].size+t[x].w;}
inline void rturn(int &x){
    int c=lc;lc=t[c].r;t[c].r=x;
    t[c].size=t[x].size;update(x);x=c;
}
inline void lturn(int &x){
    int c=rc;rc=t[c].l;t[c].l=x;
    t[c].size=t[x].size;update(x);x=c;
}
void treIns(int &x,int v){
    if(x==0){
        x=++sz;
        t[x].l=t[x].r=0;t[x].v=v;
        t[x].w=t[x].size=1;
        t[x].rnd=rand();
    }else{
        t[x].size++;
        if(v==t[x].v) t[x].w++;
        else if(v<t[x].v){
            treIns(lc,v);
            if(t[lc].rnd<t[x].rnd) rturn(x);
        }else{
            treIns(rc,v);
            if(t[rc].rnd<t[x].rnd) lturn(x);
        }
    }
}
void treDel(int &x,int v){
    if(x==0) return;
    if(v==t[x].v){
        if(t[x].w>1) t[x].w--,t[x].size--;
        else if(!lc||!rc) x=lc|rc;
        else if(t[lc].rnd<t[rc].rnd) rturn(x),treDel(x,v);
        else lturn(x),treDel(x,v);
    }else{
        t[x].size--;
        if(v<t[x].v) treDel(lc,v);
        else treDel(rc,v);
    }
}
int kth(int x,int k){
    if(x==0) return 0;
    if(k<=t[lc].size) return kth(lc,k);
    else if(k<=t[lc].size+t[x].w) return t[x].v;
    else return kth(rc,k-t[lc].size-t[x].w);
}
inline int findMin(int x){
    if(x==0) return 1e9;
    while(lc) x=lc;
    return t[x].v;
}
int Erase(int &x,int v){
    if(x==0) return 0;
    int _;
    if(t[x].v<v) {_=t[lc].size+t[x].w,x=rc;return _+Erase(x,v);}
    else {_=Erase(lc,v);t[x].size-=_;return _;}
}
int main(int argc, const char * argv[]) {
    freopen("in","r",stdin);
    srand(317);
    n=read();lim=read();
    int delcnt=0;
    for(int i=1;i<=n;i++){
        scanf("%s",s);v=read();
        if(s[0]=='I') {if(v>=lim) treIns(root,v-all);}
        else if(s[0]=='A') all+=v;
        else if(s[0]=='S'){
            all-=v;
            //int mn=findMin(root);//printf("mn %d\n",mn);
            //while(mn+all<lim) treDel(root,mn),delcnt++,mn=findMin(root);
            delcnt+=Erase(root,lim-all);
        }else{
            if(v>t[root].size) puts("-1");
            else printf("%d\n",kth(root,t[root].size-v+1)+all);
        }
    }
    printf("%d",delcnt);
}

 

posted @ 2017-03-02 23:46  Candy?  阅读(412)  评论(0编辑  收藏  举报