• BZOJ1503 [NOI2004]郁闷的出纳员


    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1503

    【我的感受】

    这题郁闷了很久,因为discuss里讨论的问题和我都不是一个问题...

    discuss里的当然是一大坑点啦,就是初始工资挂了的不算在最后踢出的人数中。

    不过这个我倒是刚开始就这么打的...不过我一直超时啊超时啊...

    终于要来了数据...额,原来是平衡树的性质都没怎么用...根本没转几次啊,然后数据就特意卡了这个,连续添加递增工资的人[变成了链]

    那我就随机转一转好了,然后不知道为什么不能srand(time(0)),反正这样就会RE,于是干脆不加随机种子了,终于搞定了...

    【分析】

    这题我的思路大概是这样的:

    1.因为不管是加工资还是减工资还是加成员还是问第k大,都和数据的数值有关而与顺序无关,于是按数值大小建立二叉树

    2.这题和平常做的+tag的题只有一种区别,就是删除和减工资一起执行了。于是需要将会被删掉的人事先找出来,即 工资<最低工资+扣减工资 的人,这当然是一颗子树啦,删掉就好。

    3.其它的操作就和之前的一样了,因为每次的增工资和减工资都是对所有人进行,所以相对大小不会变,下次如果将区间增加值...那就麻烦大了[怎么做呢?我自然是想不到了...]

    #include<cstdio>
    #include<ctime>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    
    inline int in(){
        int x=0;char ch=getchar();
        while(ch>'9' || ch<'0') ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    
    const int maxn=100010;
    
    struct Node{
        int f,ch[2];
        int sz,ct;
        int dt,pt;
    }s[maxn];
    
    int m,Min,n,rt;
    
    void push_down(int x){
        if(!s[x].pt) return;
        if(s[x].ch[0]) s[s[x].ch[0]].dt+=s[x].pt,s[s[x].ch[0]].pt+=s[x].pt;
        if(s[x].ch[1]) s[s[x].ch[1]].dt+=s[x].pt,s[s[x].ch[1]].pt+=s[x].pt;
        s[x].pt=0;
    }
    
    void update(int x){
        s[x].sz=s[s[x].ch[0]].sz+s[s[x].ch[1]].sz+s[x].ct;
    }
    
    int Find(int k){
        int p=rt;
        if(s[rt].sz<k || k<=0) return -1;
        while(p){
            push_down(p);
            if(k<=s[s[p].ch[0]].sz) p=s[p].ch[0];
            else{
                k-=s[s[p].ch[0]].sz;
                if(k<=s[p].ct) return p;
                k-=s[p].ct;p=s[p].ch[1];
            }
        }
    }
    
    void Rotate(int x,int k){
        int y=s[x].f;s[x].f=s[y].f;
        if(s[y].f){
            if(s[s[y].f].ch[0]==y) s[s[y].f].ch[0]=x;else s[s[y].f].ch[1]=x;}
        s[y].ch[k]=s[x].ch[k^1];
        if(s[x].ch[k^1]) s[s[x].ch[k^1]].f=y;
        s[y].f=x,s[x].ch[k^1]=y;
        update(y),update(x);
    }
    
    void Splay(int x,int gf){
        int y;
        while(s[x].f!=gf){
            y=s[x].f;
            if(s[y].f==gf){
                if(x==s[y].ch[0]) Rotate(x,0); else Rotate(x,1);}
            else{
                int z=s[y].f;
                if(y==s[z].ch[0]){
                    if(x==s[y].ch[0]) Rotate(y,0),Rotate(x,0);else Rotate(x,1),Rotate(x,0);}
                else{
                    if(x==s[y].ch[1]) Rotate(y,1),Rotate(x,1);else Rotate(x,0),Rotate(x,1);}
            }
        }
        if(!gf) rt=x;
    }
    
    void Insert(int x){
        if(x<Min) return;
        if(!rt){s[++n].dt=x;s[n].sz=1;rt=n,s[n].ct=1;return;}
        int p=rt;
        while(p){
            s[p].sz++;
            push_down(p);
            if(s[p].dt<x){
                if(s[p].ch[1]) p=s[p].ch[1];
                else{
                    s[p].ch[1]=++n,s[n].dt=x,s[n].sz=1,s[n].f=p,s[n].ct=1;break;
                }
            }
            else if(s[p].dt>x){
                if(s[p].ch[0]) p=s[p].ch[0];
                else{
                    s[p].ch[0]=++n,s[n].dt=x,s[n].sz=1,s[n].f=p,s[n].ct=1;break;
                }
            }
            else{
                n++;s[p].ct++;return;
            }
        }
        if(rand()%100>80) Splay(n,0);
    }
    
    void Addition(int x){
        s[rt].dt+=x,s[rt].pt+=x;
    }
    
    void Shorten(int x){
        int p=rt,bye=Min+x,rec=-1;
        while(p){
            push_down(p);
            if(s[p].dt<bye)
                rec=p,p=s[p].ch[1];
            else
                p=s[p].ch[0];
        }
        if(rec!=-1){
            Splay(rec,0);
            rt=s[rec].ch[1],s[rt].f=0;
            if(rt) update(rt);
        }
        if(rt) s[rt].dt-=x,s[rt].pt-=x;
    }
    
    int Get_kth(int k){
        int x=Find(s[rt].sz-k+1);
        if(x<0) return -1;
        if(rand()%100>80) Splay(x,0);
        return s[x].dt;
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("1503.in","r",stdin);
        freopen("1503.out","w",stdout);
    #endif
        
        int k;
        char ord[2];
        
        scanf("%d%d",&m,&Min);
        while(m--){
            scanf("%s",ord);k=in();
            if(ord[0]=='I') Insert(k);
            else if(ord[0]=='A') Addition(k);
            else if(ord[0]=='S') Shorten(k);
            else if(ord[0]=='F') printf("%d
    ",Get_kth(k));
        }
        printf("%d",n-s[rt].sz);
        
        return 0;
    }
    View Code
  • 相关阅读:
    iis 5.0 不能运行 asp.net 的 原因
    股票在线讨论
    adsl 加 路由器 网关不能上网的 原因
    汽车英语
    势与子的辩证法
    中国上海的黑心培训学校
    excel 里的 图表的使用
    带宽 下载速度 比特 率 换算 速度
    硬盘分区表修复秘籍
    Bootstrap a标签的单击时停止传播事件
  • 原文地址:https://www.cnblogs.com/Robert-Yuan/p/5089930.html
Copyright © 2020-2023  润新知