ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

万恶的平衡树

2022-06-18 12:33:00  阅读:109  来源: 互联网

标签:rt 万恶 cnt return val int 平衡 root


以普通平衡树为例

有旋Treap

#include <iostream>
#include <cstdlib>
using namespace std;
inline int in(){
	int x = 0;
	bool f = 1;
	char c = getchar();
	while(c > '9' || c < '0'){
		if(c == '-') f = 0;
		c = getchar();
	}
	while(c <= '9' && c >= '0'){
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	if(f) return x;
	else return -x;
}
const int N = 1e5+10;
const int inf = 0x7fffffff;
struct treap{
	int l,r;//左右子树 
	int val;//关键码
	int dat;//权值 
	int sz;//子树大小
	int cnt;//相同的关键码的个数,插入++,删除--,减为0删除该节点 
}a[N];
int n,tot,root;
inline int New(int val){
	a[++tot].val = val;
	a[tot].dat = rand();
	a[tot].cnt = a[tot].sz = 1;
	return tot;
}
inline void update(int rt){
	a[rt].sz = a[a[rt].l].sz + a[a[rt].r].sz + a[rt].cnt;
}
inline void build(){
	New(-inf);
	New(inf);
	root = 1;
	a[1].r = 2;
	update(root);
}
inline void zag(int &rt){//左旋
	int x = a[rt].r;
	a[rt].r = a[x].l;
	a[x].l = rt;
	rt = x;
	update(a[rt].l);
	update(rt);
}
inline void zig(int &rt){//右旋
	int x = a[rt].l;
	a[rt].l = a[x].r;
	a[x].r = rt;
	rt = x;
	update(a[rt].r);
	update(rt);
}
inline void insert(int &rt,int val){
	if(!rt){
		rt = New(val);
		return;
	}
	if(val == a[rt].val){
		a[rt].cnt++;
		update(rt);
		return;
	}
	if(a[rt].val < val){
		insert(a[rt].r,val);
		if(a[rt].dat < a[a[rt].r].dat) zag(rt);//不满足堆性质,左旋 
	}else{
		insert(a[rt].l,val);
		if(a[rt].dat < a[a[rt].l].dat) zig(rt);//右旋
	}
	update(rt);
}
inline void dlt(int &rt,int val){
	if(!rt) return;
	if(a[rt].val == val){
		if(a[rt].cnt > 1){
			a[rt].cnt--;
			update(rt);
			return;
		}
		if(a[rt].l || a[rt].r){//如果不是叶子节点,转下去 
			if(!a[rt].r || a[a[rt].l].dat > a[a[rt].r].dat){
				zig(rt);
				dlt(a[rt].r,val);
			}else{
				zag(rt);
				dlt(a[rt].l,val);
			}
			update(rt);
		}else rt = 0;
		return;
	}
	if(val < a[rt].val) dlt(a[rt].l,val);
	else dlt(a[rt].r,val);
	update(rt);
}
inline int gtr(int rt,int val){
	if(!rt) return 0;
	if(val == a[rt].val) return a[a[rt].l].sz + 1;
	if(val < a[rt].val) return gtr(a[rt].l,val);
	else return gtr(a[rt].r,val) + a[a[rt].l].sz + a[rt].cnt;
}
inline int gtv(int rt,int rank){
	if(!rt) return 0;
	if(a[a[rt].l].sz >= rank) return gtv(a[rt].l,rank);
	else if(a[a[rt].l].sz + a[rt].cnt >= rank) return a[rt].val;
	else return gtv(a[rt].r,rank-a[a[rt].l].sz-a[rt].cnt);
}
inline int gtp(int val){
	int ans = 1;//a[1].val = -inf
	int rt = root;
	while(rt){
		if(val == a[rt].val){
			if(a[rt].l){
				rt = a[rt].l;
				while(a[rt].r) rt = a[rt].r;
				ans = rt;
			}
			break;
		}
		if(a[rt].val < val && a[rt].val > a[ans].val) ans = rt;
		if(val < a[rt].val) rt = a[rt].l;
		else rt = a[rt].r;
	}
	return a[ans].val;
}
inline int gtn(int val){
	int ans = 2;//a[2].val = inf
	int rt = root;
	while(rt){
		if(val == a[rt].val){
			if(a[rt].r){
				rt = a[rt].r;
				while(a[rt].l) rt = a[rt].l;
				ans = rt;
			}
			break;
		}
		if(a[rt].val > val && a[rt].val < a[ans].val) ans = rt;
		if(val < a[rt].val) rt = a[rt].l;
		else rt = a[rt].r;
	}
	return a[ans].val;
}
int main(){
	build();
	n = in();
	int opt,x;
	while(n--){
		opt = in();
		x = in();
		if(opt == 1) insert(root,x);
		else if(opt == 2) dlt(root,x);
		else if(opt == 3) printf("%d\n",gtr(root,x)-1);
		else if(opt == 4) printf("%d\n",gtv(root,x+1));
		else if(opt == 5) printf("%d\n",gtp(x));
		else if(opt == 6) printf("%d\n",gtn(x)); 
	}
	return 0;
}

Splay

#include <iostream>
#include <cstdlib>
#define fa(x) a[x].fa
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
#define sz(x) a[x].sz
#define cnt(x) a[x].cnt
#define val(x) a[x].val
using namespace std;
inline int in(){
    int x = 0;
    bool f = 1;
    char c = getchar();
    while(c > '9' || c < '0'){
        if(c == '-') f = 0;
        c = getchar();
    }
    while(c <= '9' && c >= '0'){
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    if(f) return x;
    else return -x;
}
const int N = 1e5+100;
const int inf = 0x7ffffff;
struct splay{
	int fa;
	int ch[2];
	int val;
	int cnt;
	int sz;
}a[N];
int n,tot,root,ans;
inline void update(int rt){
	sz(rt) = sz(ls(rt)) + sz(rs(rt)) + cnt(rt);
}
inline bool get(int rt){
	return rt == rs(fa(rt));
}
inline void clear(int rt){
    fa(rt) = val(rt) = cnt(rt) = sz(rt) = ls(rt) = rs(rt) = 0;
}
inline void rotate(int rt){
	int f = fa(rt);
	int pa = fa(f);
    int cnt = get(rt);
    a[f].ch[cnt] = a[rt].ch[cnt^1];
    if(a[rt].ch[cnt^1]) fa(a[rt].ch[cnt^1]) = f;
    a[rt].ch[cnt^1] = f;
    fa(f) = rt;
    fa(rt) = pa;
    if(pa) a[pa].ch[f == rs(pa)] = rt;
    update(rt);
    update(f);
}
inline void splay(int rt){
	for(int f = fa(rt);f = fa(rt),f;rotate(rt))
        if(fa(f)) rotate(get(rt) == get(f) ? f : rt);
    root = rt;
}
inline void insert(int val){
	if(!root){
		val(++tot) = val;
		cnt(tot) = 1;
		root = tot;
		update(root);
		return;
	}
	int rt = root,f = 0;
	while(1){
		if(val(rt) == val){
			cnt(rt)++;
			update(rt);
			update(f);
			splay(rt);
			break;
		}
		f = rt;
        rt = a[rt].ch[val(rt) < val];
		if(!rt){
			val(++tot) = val;
			cnt(tot) = 1;
			fa(tot) = f;
            a[f].ch[val(f) < val] = tot;
			update(tot);
			update(f);
			splay(tot);
			break;
		}
	}
}
inline int rk(int val){//查询val的排名
    int res = 0,cnt = root;
    while(1){
        if(val < val(cnt)) cnt = ls(cnt);
        else{
            res += sz(ls(cnt));
            if(val == val(cnt)){
                splay(cnt);
                return res + 1;
            }
            res += cnt(cnt);
            cnt = rs(cnt);
        }
    }
}
inline int kth(int k){//查询排名为k的数
    int cnt = root;
    while(1){
        if(ls(cnt) && k <= sz(ls(cnt))) cnt = ls(cnt);
        else{
            k -= cnt(cnt) + sz(ls(cnt));
            if(k <= 0){
                splay(cnt);
                return val(cnt);
            }
            cnt = rs(cnt);
        }
    }
}
inline int pre(){
    int cnt = ls(root);
    if(!cnt) return cnt;
    while(rs(cnt)) cnt = rs(cnt);
    splay(cnt);
    return cnt;
}
inline int nxt(){
    int cnt = rs(root);
    if(!cnt) return cnt;
    while(ls(cnt)) cnt = ls(cnt);
    splay(cnt);
    return cnt;
}
inline void dlt(int val){
    rk(val);
    if(cnt(root) > 1){
        cnt(root)--;
        update(root);
        return;
    }
    if(!ls(root) && !rs(root)){
        clear(root);
        root = 0;
        return;
    }
    if(!ls(root)){
        int cnt = root;
        root = rs(root);
        fa(root) = 0;
        clear(cnt);
        return;
    }
    if(!rs(root)){
        int cnt = root;
        root = ls(root);
        fa(root) = 0;
        clear(cnt);
        return;
    }
    int cnt = root;
    int x = pre();
    fa(rs(cnt)) = x;
    rs(x) = rs(cnt);
    clear(cnt);
    update(root);
}
int main(){
	n = in();
	int x,opt;
    for(int i = 1;i <= n;++i){
        opt = in();
        x = in();
        if(opt == 1) insert(x);
        if(opt == 2) dlt(x);
        if(opt == 3) printf("%d\n",rk(x));
        if(opt == 4) printf("%d\n",kth(x));
        if(opt == 5){
            insert(x);
            printf("%d\n",val(pre()));
            dlt(x);
        }
        if(opt == 6){
            insert(x);
            printf("%d\n",val(nxt()));
            dlt(x);
        }
	}
    return 0;
}

裂开。。。。。TAT

标签:rt,万恶,cnt,return,val,int,平衡,root
来源: https://www.cnblogs.com/Kamisato-Ayaka/p/16388089.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有