• 【BZOJ】3224: Tyvj 1728 普通平衡树(某不科学的oj)


    http://www.lydsy.com/JudgeOnline/problem.php?id=3224

    无力吐槽,无力吐槽,无力吐槽.......

    bzoj竟然不能用time(0)我竟然不造!!re成一片。。。。。

    (不管re没re,我也在我程序中找到了很多bug,,,一一修复了。。我的treap写的真渣。

    这次我发现了treap的很多问题,有一个细节的地方。就是null的weight必须要最大(或最小),你的堆是最小(或最大)的话,所以要将null的weight的初值设置一下,否则在删除操作的时候会吧null旋转上去。。然后就,,

    这个题还有一个hentai的地方,就是求前驱后继以及排名和第k小,全是坑,首先是有多个相同的要最小的,然后又是求前驱后继不是在树里面有的。。经过观赏大神们的代码,我一一解决了。现在放上代码

    #include <cstdio>
    #include <cstdlib>
    
    using namespace std;
    const int oo=~0u>>1;
    
    struct Treap {
    	struct node {
    		node* ch[2];
    		int key, size, wei, cnt; //多加一个维
    		node(int _key, node* f) { ch[0]=ch[1]=f; key=_key; size=cnt=1; wei=rand(); }
    		void pushup() { size=ch[0]->size+ch[1]->size+cnt; } //用cnt来更新
    	}*null, *root;
    	Treap() {
    		null=new node(0, 0);
    		null->size=null->cnt=0;  null->wei=oo; //细节
    		root=null;
    	}
    	void rot(node* &rt, bool d) {
    		node* c=rt->ch[!d]; rt->ch[!d]=c->ch[d]; c->ch[d]=rt;
    		rt->pushup(); c->pushup();
    		rt=c;
    	}
    	void insert(const int &key, node* &rt) {
    		if(rt==null) { rt=new node(key, null); return; }
    		if(key==rt->key) {
    			rt->cnt++; rt->size++;
    			return;
    		}
    		bool d=key>rt->key;
    		insert(key, rt->ch[d]);
    		if(rt->wei>rt->ch[d]->wei) rot(rt, !d); //我是弄成小根堆
    		rt->pushup();
    	}
    	void remove(const int &key, node* &rt) {
    		if(rt==null) return;
    		bool d=key>rt->key;
    		if(key==rt->key) {
    			if(rt->cnt>1) { rt->cnt--; rt->size--; return; }
    			d=rt->ch[0]->wei>rt->ch[1]->wei; //巧妙的用上了null的weight最大
    			if(rt->ch[d]==null) {
    				delete rt;
    				rt=null;
    				return;
    			}
    			rot(rt, !d);
    			remove(key, rt->ch[!d]);
    		}
    		else remove(key, rt->ch[d]);
    		rt->pushup();
    	}
    	node* select(int k, node* rt) {
    		int s=rt->ch[0]->size+rt->cnt;
    		if(k>=rt->ch[0]->size+1 && k<=s) return rt; //这里要注意,因为有多个相同值,所以要判断区间
    		if(s>k) return select(k, rt->ch[0]);
    		else return select(k-s, rt->ch[1]);
    	}
    	int rank(const int &key, node* rt) {
    		if(rt==null) return 0;
    		int s=rt->ch[0]->size+rt->cnt;
    		if(key==rt->key) return rt->ch[0]->size+1; //这里要注意,返回的要是第一个
    		if(key<rt->key) return rank(key, rt->ch[0]);
    		else return s+rank(key, rt->ch[1]);
    	}
    	int suc(const int &k) {
    		node* t=root;
    		int ret=0;
    		while(t!=null) {
    			if(t->key>k) {
    				ret=t->key;
    				t=t->ch[0];
    			}
    			else t=t->ch[1];
    		}
    		return ret;
    	}
    	int pre(const int &k) {
    		node* t=root;
    		int ret=0;
    		while(t!=null) {
    			if(t->key<k) {
    				ret=t->key;
    				t=t->ch[1];
    			}
    			else t=t->ch[0];
    		}
    		return ret;
    	}
    };
    
    int main() {
    	int n, a, b;
    	Treap tree;
    	scanf("%d", &n);
    	while(n--) {
    		scanf("%d%d", &a, &b);
    		if(a==1) tree.insert(b, tree.root);
    		else if(a==2) tree.remove(b, tree.root);
    		else if(a==3) printf("%d
    ", tree.rank(b, tree.root));
    		else if(a==4) printf("%d
    ", tree.select(b, tree.root)->key);
    		else if(a==5) printf("%d
    ", tree.pre(b));
    		else if(a==6) printf("%d
    ", tree.suc(b));
    	}
    	return 0;
    }
    

    Description

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个)
    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)

    Input

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

    Output

    对于操作3,4,5,6每行输出一个数,表示对应答案

    Sample Input

    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598

    Sample Output

    106465
    84185
    492737

    HINT

    1.n的数据范围:n<=100000

    2.每个数的数据范围:[-1e7,1e7]

    Source

  • 相关阅读:
    如何巧妙着运用「位运算」来解决问题?
    一文读懂一台计算机是如何把数据发送给另一台计算机的
    Java集合与泛型中的几个陷阱,你掉进了几个?
    【链表问题】打卡10:将搜索二叉树转换成双向链表
    【链表问题】打卡9:将单链表的每K个节点之间逆序
    【链表问题】打卡8:复制含有随机指针节点的链表
    单例模式中的volatile关键字
    链表回文判断(基于链表反转)—Java实现
    设计模式之单例模式
    Spring的IoC与AOP的理解
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3869598.html
Copyright © 2020-2023  润新知