• BZOJ1503:[NOI2004]郁闷的出纳员


    浅谈(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
    ",T.get_val(k));
        }
        printf("%d
    ",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
    ",T.get_val(k));
        }
        printf("%d
    ",tot-T.siz[T.root]);
        return 0;
    }
    
  • 相关阅读:
    js根据年月获取当月最后一天
    skywalking 执行流程 日志放在哪里 MySQL或者ES
    SpringCloud微服务间安全调用实现(SpringSecurity+Oauth2+Jwt)
    内存泄露和内存溢出的区别
    Mybatis的执行流程
    Spring如何解决循环依赖
    Spring事务在哪几种情况下会失效?
    Spring Boot 中application.yml与bootstrap.yml的区别
    Nacos执行流程
    Gateway 如何解决跨域问题
  • 原文地址:https://www.cnblogs.com/AKMer/p/9991772.html
Copyright © 2020-2023  润新知