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\n",Get_kth(k));
    }
    printf("%d",n-s[rt].sz);

    return 0;
}

时间: 2024-10-26 20:01:28

BZOJ1503 [NOI2004]郁闷的出纳员的相关文章

bzoj1503 [NOI2004]郁闷的出纳员(名次树+懒惰标记)

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 8705  Solved: 3027[Submit][Status][Discuss] Description OIER 公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是, 我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反

[BZOJ1503][NOI2004]郁闷的出纳员 无旋Treap

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MB Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情.工资的频繁调

[BZOJ1503] [NOI2004] 郁闷的出纳员 (treap)

Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情.工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司

bzoj1503: [NOI2004]郁闷的出纳员 fhqtreap版

这道题写法和之前差不多 但是fhqtreap在加点的时候为了同时维护大根堆以及二叉排序树的性质所以插入时也要注意分裂 fhqteap需要判断指针是否为空 不然就会re 这个我调了很久 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=150000; int read(){ int ans=0,f=1,c=getchar(); while(c<

BZOJ1503 NOI2004 郁闷的出纳员 平衡树

题意:开始时给定一个空的数列,要求维护:1.加入一个数  2.数列中所有元素+k  3.数列中所有元素-k  4.查询数列中的第k大.其中对于任意时刻,如果有一个元素<Min,则删除该元素. 题解:平衡树裸题……话说当年还打算把Splay Treap SBT都学一下,结果现在只会Splay了QAQ #include <cstdio> #include <cstring> #include <cstdlib> #include <climits> #in

【权值分块】bzoj1503 [NOI2004]郁闷的出纳员

权值分块,离散化非常蛋疼,只能离散化搞…… 需要支持操作:删除<=某个值得所有权值==打标记 O(sqrt(n)) 码长和我的平衡树差不多……速度快3倍左右. 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 #define N 201001 7 struct Point{int v,p;}tmp

1503: [NOI2004]郁闷的出纳员 Treap

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 6263  Solved: 2190[Submit][Status] Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可

[BZOJ 1503] [NOI2004] 郁闷的出纳员

1503: [NOI2004] 郁闷的出纳员 Time Limit: 5 SecMemory Limit: 64 MB Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情.工资的频繁调整

BZOJ 题目1503: [NOI2004]郁闷的出纳员(SBT+延迟操作)

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 8058  Solved: 2828 [Submit][Status][Discuss] Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反