• [NOI2004]郁闷的出纳员(到底是谁郁闷啊?)


    一道 FHQ treap 的裸水题,卡了这么久。(咦~一看就是修为不够

     

    题解什么的,不用看的(话说那我为什么要写这篇题解咧...),直接 FHQ 模板腾上去就能秒 A 了(打脸)

     

    谈谈 debug ...  首先是一个 0 写成了 1 ,GG ,然后是 m-1 出现了乱七八糟的东西,然后又被误导在 insert 操作不执行时 ++res ... 等,以上

    咦~这个人一看就是菜鸡这么裸的题都要 debug 这么久)(*/ω\*)

     

    所以就是 要套 FHQ 里面的merge 、split_key、split_val、get_rank、ins (以及一些update 、pushdown、rand 什么零碎操作)

    如果你还不是很了解 FHQ treap ,可以看这里

    然后这题的增减工资其实可以打一下懒标记的啦~(一开始没搞清楚状况没用懒标记直接对 m 进行操作,后来发现这个增减工资只对操作前存在的员工有用啊!),

    split 的时候 pushdown 一下就好了(merge 是不用的,因为这里没有直接merge的操作,都是先split完了之后才merge的)

     

    所以...上代码...

     

    //by Judge
    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int M=2e5+111;
    //#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<21],*p1=buf,*p2=buf;
    inline int read(){
        int x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
    }
    inline int cread(){
        char c=getchar();
        while(!isupper(c)) c=getchar();
        switch(c){
            case 'I': return 1;
            case 'A': return 2;
            case 'S': return 3;
            case 'F': return 4;
        }
    }
    char sr[1<<21],z[20];int C=-1,Z;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    inline void print(int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    }
    int n,m,q,res,cnt,root;
    struct Node { int val,key,siz,tag,ch[2]; } t[M];
    inline int Rand() { static int seed=998; return seed=int(seed*48271LL%(~0u>>1)); }
    inline void update(int now){ t[now].siz=t[t[now].ch[0]].siz+t[t[now].ch[1]].siz+1; }
    inline void pushdown(int now){ //多了pushdown
        t[t[now].ch[0]].val+=t[now].tag,t[t[now].ch[1]].val+=t[now].tag,
        t[t[now].ch[0]].tag+=t[now].tag,t[t[now].ch[1]].tag+=t[now].tag,t[now].tag=0;
    }
    int merge(int u,int v) {
        if(!u || !v) return u|v;
        if(t[u].key<t[v].key) { t[u].ch[1]=merge(t[u].ch[1],v),update(u); return u; }
        else { t[v].ch[0]=merge(u,t[v].ch[0]),update(v); return v; }
    }
    void split_val(int now,int k,int& x,int& y) {
        if(!now) return (void)(x=y=0); pushdown(now);
        if(t[now].val<=k) split_val(t[x=now].ch[1],k,t[now].ch[1],y);
        else split_val(t[y=now].ch[0],k,x,t[now].ch[0]); update(now);
    }
    void split_k(int now,int k,int& x,int& y) {
        if(!now) return (void)(x=y=0); pushdown(now);
        if(t[t[now].ch[0]].siz>=k) split_k(t[y=now].ch[0],k,x,t[now].ch[0]),update(now);
        else split_k(t[x=now].ch[1],k-t[t[now].ch[0]].siz-1,t[now].ch[1],y),update(now);
    }
    inline void ins(int x) { int u,a,b; t[u=++cnt].key=Rand(),t[u].val=x,t[u].siz=1,split_val(root,x,a,b),root=merge(merge(a,u),b); }
    inline int get_val(int x) { int a,b,c,d,e; split_k(root,x-1,a,b),split_k(b,1,c,d),e=t[c].val,root=merge(a,merge(c,d)); return e; }
    signed main() {
        n=read(),m=read()-1;
        for(int opt,x;n;--n){
            opt=cread(),x=read();
            switch(opt){ //四个较为常规的操作
                case 1: if(x>m) ins(x); break;
                case 2: t[root].val+=x,t[root].tag+=x; break;
                case 3: t[root].val-=x,t[root].tag-=x,split_val(root,m,x,root),res+=t[x].siz; break;
                case 4: print(x>t[root].siz?-1:get_val(t[root].siz-x+1)); break;
            } Ot();
        } print(res),Ot(); return 0;
    }

     

  • 相关阅读:
    [转]我在Facebook学到的10个经验
    [转]MPlayer快捷键&参数设置>系统开销最少的影音播放器
    [转]国外程序员推荐:每个程序员都应读的书
    Linux运维:CentOS6和7的区别
    将数组中指定的前N位移动到数组的最后面
    DataReader和DataSet区别
    求数组中和最大的子数组与始末下标
    使用XPathExpression类对XML文件进行排序
    配置WebSite的IIS时遇到的问题与解决方法
    已知一个整数N,求另外一个整数M,使得M本身 + M各个位上的数 = N
  • 原文地址:https://www.cnblogs.com/Judge/p/9539271.html
Copyright © 2020-2023  润新知