zoukankan      html  css  js  c++  java
  • BSTTreap名次树数组&指针实现板子 Ver1.0

    这里只有板子没有原理QWQ

    可实现

    1.插入 x 数

    2.删除 x 数(若有多个相同的数,只删除一个)

    3.查询 x 数的排名(排名定义为比当前数小的数的个数 +1)

    4.查询排名为 x 的数

    5.求 x 的前驱(前驱定义为小于 x,且最大的数)

    6.求 x 的后继(后继定义为大于 x,且最小的数)

    原题 https://www.luogu.com.cn/problem/P3369

    目前看来,指针板子相对数组板子相对好写,虽然时间稍快,但是空间稍劣,而且所有指针都要初始化为null,不初始化为null无法insert进去。

    数组板子 374ms 2.78MB

    指针板子 315ms 2.82MB

    数组板子 374ms 2.78MB

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define IL  inline
    typedef long long LL;
    
    const int N = 1e5 + 3;
    
    struct Node {
    	int ch[2],v,sz,r,cnt;
    	IL bool operator < (const Node& rhs) const { return r < rhs.r;}
    	IL int cmp(int x) const {
    		if(x == v) return -1;
    		return x > v;
    	}
    };
    struct Treap {
    	int sz,root,ans;
    	Node tr[N];
    	IL void init() {tr[0].ch[0]=tr[0].ch[1]=tr[0].sz=tr[0].cnt=tr[0].r=0; root = 0;}
    	IL void upd(int o) { tr[o].sz=tr[tr[o].ch[0]].sz+tr[tr[o].ch[1]].sz+tr[o].cnt;}
    	IL void rotate(int &o,int d) {
    		int k = tr[o].ch[d^1]; tr[o].ch[d^1]=tr[k].ch[d]; tr[k].ch[d] = o;
    		upd(o); upd(k); o = k;
    	}
    	void insert(int &o,int x) {
    		if(o == 0) {
    			o=++sz;
    			tr[o].ch[0] = tr[o].ch[1] = 0;
    			tr[o].sz = tr[o].cnt=1;
    			tr[o].v = x; tr[o].r = rand();
    			return;
    		}
    		tr[o].sz++;
    		int d = tr[o].cmp(x);
    		if(d == -1) { tr[o].cnt++; return;}
    		insert(tr[o].ch[d],x);
    		if(tr[tr[o].ch[d]].r > tr[o].r) rotate(o,d^1);
    		upd(o);
    	}
    	void erase(int &o,int x) {
    		if(o == 0) return;
    		int d = tr[o].cmp(x);
    		if(d == -1) {
    			if(tr[o].cnt > 1) { tr[o].cnt--; tr[o].sz--; return;}
    			if(tr[o].ch[0]*tr[o].ch[1]==0) { o = tr[o].ch[0] + tr[o].ch[1];}
    			else {
    				int d2 = tr[tr[o].ch[0]].r > tr[tr[o].ch[1]].r;
    				rotate(o,d2); erase(tr[o].ch[d2],x);
    			}
    		}
    		else erase(tr[o].ch[d],x);
    		upd(o);
    	}
    	int query_rank(int o,int x) { //查询x的排名 
    		if(o == 0) return 1;
    		if(tr[o].v==x) return tr[tr[o].ch[0]].sz+1;
    		else if(x > tr[o].v) 
    			return tr[tr[o].ch[0]].sz+tr[o].cnt+query_rank(tr[o].ch[1],x);
    		else return query_rank(tr[o].ch[0],x);
    	}
    	int query_kth(int o,int x) { //查询排名为x的数 
    		if(o == 0) return 0;
    		if(x <= tr[tr[o].ch[0]].sz) return query_kth(tr[o].ch[0],x);
    		else if(x>tr[tr[o].ch[0]].sz+tr[o].cnt)
    			return query_kth(tr[o].ch[1],x-tr[tr[o].ch[0]].sz-tr[o].cnt);
    		else return tr[o].v;	 
    	}
    	void query_pre(int o,int x) { // 查询x的前驱 
    		if(o == 0) return;
    		if(tr[o].v < x) {
    			ans = o; query_pre(tr[o].ch[1],x);
    		}
    		else query_pre(tr[o].ch[0],x);
    	}
    	void query_sub(int o,int x) { // 查询x的后继 
    		if(o == 0) return;
    		if(tr[o].v > x) {
    			ans = o; query_sub(tr[o].ch[0],x);
    		}
    		else query_sub(tr[o].ch[1],x);
    	}
    	IL void ins(int x) {insert(root,x); return;}
    	IL void del(int x) {erase(root,x); return;}
    	IL int rank(int x) {return query_rank(root,x);} //return rank of x
    	IL int kth(int x) {return query_kth(root,x);} // return the number,which rank=x.
    	IL int pre(int x) {ans=0; query_pre(root,x); return ans;}
    	IL int sub(int x) {ans=0; query_sub(root,x); return ans;}
    };
    
    Treap tr;
    int main() {
    	int n; scanf("%d",&n);
    	int op,x;
    	tr.init();
    	for(int i=0;i<n;i++) {
    		scanf("%d%d",&op,&x);
    		switch(op) {
    			case 1: tr.ins(x); break;
    			case 2: tr.del(x); break;
    			case 3: printf("%d\n",tr.rank(x)); break;
    			case 4: printf("%d\n",tr.kth(x)); break;
    			case 5: printf("%d\n",tr.tr[tr.pre(x)].v); break;
    			case 6: printf("%d\n",tr.tr[tr.sub(x)].v); break;
    		}
    	}
    }
    

    指针板子 315ms 2.82MB

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    #define IL inline 
    typedef long long LL;
    const int N = 1e5 + 3;
    
    struct Node *null;
    struct Node {
    	Node *ch[2];
    	int v,sz,r,cnt;
    	IL Node() {}
    	IL Node(int v):v(v) {ch[0]=ch[1]=null; r=rand(); sz=cnt=1;}
    	IL bool operator < (const Node& rhs) const { return r < rhs.r;}
    	IL int cmp(int x) const {
    		if(x == v) return -1;
    		return v < x;
    	}
    	IL void upd() { sz = ch[0] -> sz + ch[1] -> sz + cnt;}
    };
    
    IL void initnull() {null = new Node(); null->v=null->sz=null->r=null->cnt=0;}
    IL void rotate(Node* &o,int d) {
    	Node *k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o;
    	o->upd(); k->upd(); o = k;
    }
    void insert(Node* &o,int x) {
    	if(o == null) {o = new Node(x); return;}
    	o->sz++;
    	int d = o->cmp(x);
    	if(d == -1) {o->cnt++; return;}
    	insert(o->ch[d],x);
    	if(o->r < o->ch[d]->r) rotate(o,d^1);
    	o -> upd();
    }
    void erase(Node* &o,int x) {
    	if(o == null) return;
    	int d = o->cmp(x);
    	if(d == -1) {
    		Node* u = o;
    		if(o->cnt > 1) {o->cnt--; o->sz--; return;}
    		if(o->ch[0] != null && o->ch[1] != null) {
    			int d2 = o->ch[0]->r > o->ch[1]->r;
    			rotate(o,d2); erase(o->ch[d2],x);
    		}
    		else {
    			if(o->ch[0] == null) o = o->ch[1]; else o = o->ch[0];
    			delete u;
    		}
    	}
    	else erase(o->ch[d],x);
    	if(o != null) o->upd();
    }
    int query_rank(Node *o, int x) {
    	if(o == null) return 1;
    	if(o->v == x) return o->ch[0]->sz + 1;
    	else if(o->v < x) return o->ch[0]->sz + o->cnt + query_rank(o->ch[1],x);
    	else return query_rank(o->ch[0],x);
    }
    int query_kth(Node* o, int k) {
    	if(o == null) return 0;
    	if(k <= o->ch[0]->sz) return query_kth(o->ch[0],k);
    	else if(k > o->ch[0]->sz + o->cnt)
    		return query_kth(o->ch[1],k - o->ch[0]->sz - o->cnt);
    	return o->v;
    }
    
    Node *ans,*root;
    void query_pre(Node* o,int x) {
    	if(o == null) return;
    	if(o->v < x) { ans = o; query_pre(o->ch[1],x);}
    	else query_pre(o->ch[0],x);
    }
    void query_sub(Node* o,int x) {
    	if(o == null) return;
    	if(x < o->v) { ans = o; query_sub(o->ch[0],x);}
    	else query_sub(o->ch[1],x);
    }
    IL void ins(int x) {insert(root,x);}
    IL void del(int x) {erase(root,x);}
    IL int rank(int x) {return query_rank(root,x);}
    IL int kth(int x) {return query_kth(root,x);}
    IL int pre(int x) {ans=null;query_pre(root,x);return ans->v;}
    IL int sub(int x) {ans=null;query_sub(root,x);return ans->v;}
    
    IL void init() { initnull(); ans = root = null;}
    
    int main() {
    	int n; scanf("%d",&n);
        int op,x;
        init();
        for(int i=0;i<n;i++) {
            scanf("%d%d",&op,&x);
            switch(op) {
                case 1: ins(x); break;
                case 2: del(x); break;
                case 3: printf("%d\n",rank(x)); break;
                case 4: printf("%d\n",kth(x)); break;
                case 5: printf("%d\n",pre(x)); break;
                case 6: printf("%d\n",sub(x)); break;
            }
        }
    	return 0;
    } 
    
  • 相关阅读:
    (转)关于c#中的事件
    MySql数据库--持续记录ing
    在Eclipse中通过JDBC连接MySQL步骤,非常详细!
    mybatis传入参数类型parameterType和输出结果类型resultType详解
    关于JDBC访问存储过程的问题
    Mybatis(一)入门
    [Redis] 基于redis的分布式锁
    分布式锁----浅析redis实现
    MyBatis的增删改查操作
    C3P0连接池工具类实现步骤及方法
  • 原文地址:https://www.cnblogs.com/bringlu/p/12240940.html
Copyright © 2011-2022 走看看