[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);
} 
posted @ 2019-07-14 19:43  birchtree  阅读(239)  评论(0编辑  收藏  举报