zoukankan      html  css  js  c++  java
  • [noi 2004] 郁闷的出纳员

    原题地址


     花了一两天真正的熟悉了Treap,对于一个东西,本蒟蒻认为,不应该要会,还应会熟练的写,【像哈狗写这个只需十分钟】


    好吧,话归正题 先推荐另类解法 戳进去  


    此题解法很多BIT , 权值线段树 ,各种平衡树(准备抽空写)。。。。 是一道很棒的模板题。


    这道题我们把每次全体加的工资和减的弄到一个变量,姑且叫为w,把当前操作的数叫为k,当我们加工资时,肯定不会有员工退役把。。。所以直接将w 加上 k就行了

    如果是减工资,就有可能有员工退役了,我们就应进行一次删除操作了。。。

    那么如何删除呢?

    先把w减去k,然后遍历。

    我们遇到的节点的值 + w 如果大于等于工资下限的话,那么肯定只有可能左儿子中有小于工资下限的吧,那么就跑到它左儿子那里去。如果遇到节点的值是小于工资下限的,那么它右子树有可能有小于工资下限的,那么就一直左旋(这样就能不断地把大的旋上来),直到右节点的值是Null或当前节点的值是大于等于工资上限的,然后删除左儿子(子树)( 即把左边变为Null),如果当前节点也是小于工资上限的话也把当前节点赋为Null。。

    至于加入新的节点的话,前面的w跟他毛关系不沾对吧,就把他的值减去w就行啦!


    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<cmath>
    #include<cctype>
    #include<map>
    
    const int N = 1e5 + 7;
    
    #define R12() ((rand()<<12) + (rand()<<7) + rand())
    #define R233() (R12() % 4454515 + R12() % 45444211 + R12() % 144521 + 1)
    
    int Q,min1,w;
    
    class Treap {
    	private :
    		struct Node {
    			Node* son[2];
    			int size,num,data,hr;
    			Node () {}
    			Node (int data,Node *fl) : data(data) { son[0] = son[1] = fl; size = num = 1; hr = R233(); }
    			void update () { size = son[0] -> size + son[1] -> size + num; }
    		}*Null,*root,meme[N],*pool;
    		
    		int ball,money;
    	
    		void rotate (Node *&T,bool v) {
    			Node* Tt = T -> son[v];
    			T -> son[v] = Tt -> son[v^1];
    			Tt -> son[v^1] = T;
    			T -> update(); Tt -> update();
    			T = Tt;
    		}
    		
    		void Delete (Node *&T) {
    			if(T == Null) return ;
    			while (T -> son[1] != Null && T -> data + money <= min1) T -> son[0] = Null , rotate (T , 1);
    			if(T -> data + money <= min1) {
    				if(T -> data + money < min1) T = Null;
    				else T -> son[0] = Null , T -> size = T -> num;
    				return;	
    			}
    			Delete (T -> son[0]);
    			T -> update();
    		}
    		
    		void Insert (Node *&T) {
    			if(T == Null) { T = new (pool++) Node (ball,Null); return ; }
    			if(T -> data == ball) { ++ T -> num; ++ T -> size; return ; }
    			bool v = T -> data < ball;
    			Insert(T -> son[v]);
    			if(T -> hr < T -> son[v] -> hr) rotate (T , v);
    			else T -> update();
    		}
    	
    		int Rank (Node *&T) {
    			if(T == Null) return -1;
    			if(T -> son[1] -> size >= ball) return Rank (T -> son[1]);
    			if(T -> son[1] -> size + T -> num >= ball) return T -> data;
    			ball -= T -> son[1] -> size + T -> num; return Rank (T -> son[0]);
    		}
    	
    	public :
    		Treap () { Null = new Node(); Null -> size = Null -> num = 0; }
    		void clear() { root = Null; pool = meme; money = 0; }
    		void Ins (int xxx) { ball = xxx - money; Insert(root); }
    		void Rai (int xxx) { money += xxx; }
    		void Cut (int xxx) { money -= xxx; Delete(root); }
    		int Ran (int xxx) { ball = xxx; int k = Rank(root); return k == -1 ? -1 : k + money; }
    		int size () { return root -> size; }
    }treap;
    
    int ans;
    char opt[10];
    
    int main () {
    	scanf("%d%d",&Q,&min1);
    	treap.clear();
    	while (Q--) {
    		scanf("%s%d",opt,&w);
    		if(opt[0] == 'I' && w >= min1) {
    			treap.Ins(w);
    			++ans;
    		}
    		if(opt[0] == 'A') treap.Rai(w);
    		if(opt[0] == 'S') treap.Cut(w);
    		if(opt[0] == 'F') printf("%d
    ",treap.Ran(w));
    	}
    	printf("%d
    ",ans - treap . size());
    	return 0;
    }



    that is all.Thank you for watching.

  • 相关阅读:
    数据库 数据库编程二
    Linux 退格键不回显
    数据库 数据库编程一
    数据库 SQL语法二
    数据库 SQL语法一
    数据库 Linux下的MySQL数据库管理
    docker-compose
    winodws同步时间命令
    国内yum源的安装(163,阿里云,epel)
    postgresql双机热备、高可用方案(采用pacemaker+corosync实现)
  • 原文地址:https://www.cnblogs.com/dcoi-king/p/5353661.html
Copyright © 2011-2022 走看看