1. 程式人生 > >BZOJ1503:[NOI2004]郁悶的出納員

BZOJ1503:[NOI2004]郁悶的出納員

htm getchar sin mat nlog += getch 的人 com

淺談\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html

淺談\(fhq\)_\(treap\):https://www.cnblogs.com/AKMer/p/9981274.html

題目傳送門:https://www.lydsy.com/JudgeOnline/problem.php?id=1503

對於每個人都加工資,我們可以直接降低最低工資標準來判斷,對於減工資,我們就加標準,那麽每個人與最低標準的差值始終是正確的。

我們記一個\(now\)表示當前最低工資標準,記一個\(mn\)表示初始工資標準。那麽每次進來一個工資為\(k\)的人,我們要使他與最低工資標準的差值是正確的,就應該使\(k\)

加上\(now-mn\)

而每個人與當前最低標準的差值加上初始標準,就是真實工資。

時間復雜度:\(O(nlogn)\)

空間復雜度:\(O(n)\)

\(splay\)版代碼如下:

#include <cstdio>
#include <iostream>
using namespace std;
 
const int maxn=1e5+5;
 
char s[25];
int n,mn,now,tot;
 
int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}
 
struct Splay {
    int tot,root;
    int fa[maxn],son[maxn][2];
    int siz[maxn],cnt[maxn],val[maxn];
 
    int newnode(int v) {
        val[++tot]=v;
        siz[tot]=cnt[tot]=1;
        return tot;
    }
 
    int find(int v) {
        int u=root;
        while(val[u]!=v) {
            if(val[u]>v) {if(son[u][0])u=son[u][0];else break;}
            if(val[u]<v) {if(son[u][1])u=son[u][1];else break;}
        }
        return u;
    }
 
    int t(int u) {
        return son[fa[u]][1]==u;
    }
 
    void update(int p) {
        siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]];
    }
 
    void rotate(int u) {
        int ret=t(u),f=fa[u],s=son[u][ret^1];
        son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
        fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
        fa[f]=u;update(f);update(u);
    }
 
    void splay(int u) {
        while(fa[u]) {
            if(fa[fa[u]]) {
                if(t(fa[u])==t(u))rotate(fa[u]);
                else rotate(u);
            }
            rotate(u);
        }
        root=u;
    }
     
    void ins(int v) {
        if(!root) {root=newnode(v);return;}
        int u=find(v);
        if(val[u]==v) {siz[u]++;cnt[u]++;splay(u);return;}
        fa[newnode(v)]=u;son[u][v>val[u]]=tot;
        splay(tot);
    }
 
    void check() {
        int u=find(now);splay(u);
        if(val[u]<now) {
            u=son[u][1];
            while(son[u][0])u=son[u][0];
            splay(u);
        }
        fa[son[u][0]]=0;
        son[u][0]=0;update(u);
    }
 
    int get_val(int k) {
        int u=root,rk=siz[u]-k+1;
        if(rk<1)return -1;
        while(rk) {
            if(siz[son[u][0]]>=rk)u=son[u][0];
            if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break;
            if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1];
        }
        return val[u]+mn-now;
    }
}T;
 
int main() {
    n=read(),now=mn=read();
    for(int i=1;i<=n;i++) {
        scanf("%s",s+1);
        int k=read();
        if(s[1]=='I') {
            k+=now-mn;
            if(k<now)continue;
            T.ins(k);tot++;
        }
        if(s[1]=='A')now-=k;
        if(s[1]=='S') {
            now+=k;
            T.check();
        }
        if(s[1]=='F')printf("%d\n",T.get_val(k));
    }
    printf("%d\n",tot-T.siz[T.root]);
    return 0;
}

\(fhq\)_\(treap\)版代碼如下:

#include <ctime>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
 
const int maxn=1e5+5;
 
char s[25];
int n,m,tot,mn,now;
 
int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}
 
struct fhq_treap {
    int tot,root;
    int fix[maxn],son[maxn][2];
    int siz[maxn],cnt[maxn],val[maxn];
 
    int newnode(int v) {
        val[++tot]=v;fix[tot]=rand();
        siz[tot]=cnt[tot]=1;return tot;
    }
 
    int getkth(int u,int v,bool &bo,int delta) {
        if(!u)return 0;int ans=0;
        if(val[u]>v)ans=getkth(son[u][0],v,bo,delta);
        else if(val[u]==v) {
            if(delta)cnt[u]+=delta,siz[u]+=delta,bo=1;
            return siz[son[u][0]];
        }
        else ans=siz[son[u][0]]+cnt[u]+getkth(son[u][1],v,bo,delta);
        if(bo)siz[u]+=delta;return ans;
    }
 
    void update(int p) {
        siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]];
    }
 
    pii split(int u,int rk) {
        if(!rk)return make_pair(0,u);
        if(rk==siz[u])return make_pair(u,0);
        if(siz[son[u][0]]>=rk) {
            pii tmp=split(son[u][0],rk);
            son[u][0]=tmp.second,update(u);
            return make_pair(tmp.first,u);
        }
        else {
            pii tmp=split(son[u][1],rk-siz[son[u][0]]-cnt[u]);
            son[u][1]=tmp.first,update(u);
            return make_pair(u,tmp.second);
        }
    }
 
    int merge(int a,int b) {
        if(!a||!b) return a+b;
        if(fix[a]>fix[b])return son[a][1]=merge(son[a][1],b),update(a),a;
        else return son[b][0]=merge(a,son[b][0]),update(b),b;
    }
     
    void ins(int v) {
        bool bo=0;int rk=getkth(root,v,bo,1);
        if(bo)return;pii tmp=split(root,rk);
        root=merge(merge(tmp.first,newnode(v)),tmp.second);
    }
 
    void check() {
        bool bo=0;
        int rk=getkth(root,now,bo,0);
        pii tmp=split(root,rk);root=tmp.second;
    }
 
    int get_val(int k) {
        int u=root,rk=siz[u]-k+1;
        if(rk<1)return -1;
        while(rk) {
            if(siz[son[u][0]]>=rk)u=son[u][0];
            if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break;
            if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1];
        }
        return val[u]+mn-now;
    }
}T;
 
int main() {
    srand(time(0));
    n=read(),now=mn=read();
    for(int i=1;i<=n;i++) {
        scanf("%s",s+1);int k=read();
        if(s[1]=='I') {
            k+=now-mn;
            if(k<now)continue;
            T.ins(k);tot++;
        }
        if(s[1]=='A')now-=k;
        if(s[1]=='S') {
            now+=k;
            T.check();
        }
        if(s[1]=='F')printf("%d\n",T.get_val(k));
    }
    printf("%d\n",tot-T.siz[T.root]);
    return 0;
}

BZOJ1503:[NOI2004]郁悶的出納員