zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",kth(root,t[root].size-v+1)+all);
            }
        }
        printf("%d",delcnt);
    }
  • 相关阅读:
    Add Binary <leetcode>
    那些坑
    面试集锦
    随看随记
    View的事件处理流程
    android studio view.setId报错
    EditText的hint不显示
    EditText 焦点
    Android拍照的那些事
    微信支付提示签名错误
  • 原文地址:https://www.cnblogs.com/candy99/p/6493236.html
Copyright © 2011-2022 走看看