zoukankan      html  css  js  c++  java
  • [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
    ");
    			else printf("%d
    ",T.get_kth(all-x+1)+delta);
    		}
    	}
    	printf("%d
    ",ans);
    } 
    
  • 相关阅读:
    [LeetCode] Minimum Depth of Binary Tree 二叉树最小深度
    [LeetCode] Intersection of Two Linked Lists 两链表是否相交
    [LeetCode] Permutations II 排列
    [LeetCode] Maximum Product Subarray 连续数列最大积
    Ncut matlab 代码bug 修复
    [LeetCode] Jump Game II 贪心
    【poj2182】【poj2828】树状数组/线段树经典模型:逆序查找-空位插入法
    【hdu1828/poj1177】线段树求矩形周长并
    【hdu1255】线段树求矩形面积交
    【hdu1542】线段树求矩形面积并
  • 原文地址:https://www.cnblogs.com/birchtree/p/11185357.html
Copyright © 2011-2022 走看看