[BZOJ 1503]郁闷的出纳员(fhq treap)

[BZOJ 1503]郁闷的出纳员

题面

第一行有两个非负整数n和min。n表示下面有多少条命令,min表示工资下界。

接下来的n行,每行表示一条命令。命令可以是以下四种之一:

名称 格式 作用
I命令 I_k 新建一个工资档案,初始工资为k。如果某员工的初始工资低于工资下界,他将立刻离开公司。
A命令 A_k 把每位员工的工资加上k
S命令 S_k 把每位员工的工资扣除k
F命令 F_k 查询第k多的工资

_(下划线)表示一个空格,I命令、A命令、S命令中的k是一个非负整数,F命令中的k是一个正整数。

在初始时,可以认为公司里一个员工也没有。

分析

由于加减都是对所有员工进行的,可以直接维护一个全局变量。

发现扣除工资时,可能有多位员工离开公司。只要用fhq treap,直接按照权值split一下就可以了

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define maxn 100000
using namespace std;
int n,lim;
struct fhq_treap{
    struct node{
        int ls;
        int rs;
        int val;
        int dat;
        int sz;
        int cnt;
    }tree[maxn+5];
    int ptr;
    int xx,yy;
    int root;
    void push_up(int x){
        tree[x].sz=tree[tree[x].ls].sz+tree[tree[x].rs].sz+tree[x].cnt;
    }
    int merge(int x,int y){//val[x]<=val[y] 
        if(x==0||y==0) return x+y;
        if(tree[x].dat<tree[y].dat){
            tree[x].rs=merge(tree[x].rs,y);
            push_up(x);
            return x;
        }else{
            tree[y].ls=merge(x,tree[y].ls);
            push_up(y);
            return y;
        }
    }   
    void split(int now,int k,int &x,int &y){//把值<=k的分出来 
        if(now==0){
            x=y=0;
            return;
        }else{
            if(k>=tree[now].val){
                x=now;
                split(tree[now].rs,k,tree[x].rs,y);
            }else{
                y=now;
                split(tree[now].ls,k,x,tree[now].ls);       
            }
            push_up(now);
        }
    } 
    
    int get_kth(int k){
        int x=root;
        while(1){
            if(k<=tree[tree[x].ls].sz) x=tree[x].ls;
            else if(k<=tree[tree[x].ls].sz+tree[x].cnt) return tree[x].val;
            else{
                k-=tree[tree[x].ls].sz+tree[x].cnt;
                x=tree[x].rs;
            }
        }
        return 0;
    } 
    int New(int val){
        ptr++;
        tree[ptr].sz=tree[ptr].cnt=1;
        tree[ptr].val=val;
        tree[ptr].dat=rand();
        return ptr;
    }
    
    void insert(int val){
        split(root,val,xx,yy);
        root=merge(xx,merge(New(val),yy));
    }
    
    int del(int val){
        split(root,val,xx,yy);
        root=yy;
        return tree[xx].sz;
    }
}T;

int delta;
char cmd[2];
int main(){
    int x;
    int ans=0;
    scanf("%d %d",&n,&lim);
    for(int i=1;i<=n;i++){
        scanf("%s %d",cmd,&x);
        if(cmd[0]=='I'){
            if(x>=lim){
                x-=delta;
                T.insert(x);
            } 
        }else if(cmd[0]=='A'){
            delta+=x;
        }else if(cmd[0]=='S'){
            delta-=x;
            ans+=T.del(lim-delta-1);
        }else if(cmd[0]=='F'){
            int all=T.tree[T.root].sz;
            if(x>all) printf("-1\n");
            else printf("%d\n",T.get_kth(all-x+1)+delta);
        }
    }
    printf("%d\n",ans);
} 
上一篇:[Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)


下一篇:编程日报(第二版)——模板库