zoukankan      html  css  js  c++  java
  • Bzoj 3224 普通平衡树

    地址 https://ac.nowcoder.com/acm/contest/1036/A

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    
    插入数值 x。
    删除数值 x(若有多个相同的数,应只删除一个)。
    查询数值 x 的排名(若有多个相同的数,应输出最小的排名)。
    查询排名为 x 的数值。
    求数值 x 的前驱(前驱定义为小于 x 的最大的数)。
    求数值 x 的后继(后继定义为大于 x 的最小的数)。
    注意: 数据保证查询的结果一定存在。
    
    输入格式
    第一行为 n,表示操作的个数。
    
    接下来 n 行每行有两个数 opt 和 x,opt 表示操作的序号(1≤opt≤6)。
    
    输出格式
    对于操作 3,4,5,6 每行输出一个数,表示对应答案。
    
    数据范围
    1≤n≤100000,所有数均在 −107 到 107 内。
    
    输入样例:
    8
    1 10
    1 20
    1 30
    3 20
    4 2
    2 10
    5 25
    6 -1
    输出样例:
    2
    20
    20
    20
    

    解答
    treap树的模板题目 这里将模板记录

    // 111235.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #include <iostream>
    #include <algorithm>
    
    using  namespace std;
    
    const int N = 100010; 
    int INF = 1e8;
    
    int n;
    struct Node {
    	int l, r;
    	int key, val;
    	int cnt, size;
    }tr[N];
    int root, idx;
    
    void pushup(int p) {
    	tr[p].size = tr[tr[p].l].size +
    			tr[tr[p].r].size + tr[p].cnt;
    
    }
    
    int get_node(int key) {
    	tr[++idx].key = key;
    	tr[idx].val = rand();
    	tr[idx].cnt = tr[idx].size = 1;
    	return idx;
    }
    
    void build() {
    	get_node(-INF);
    	get_node(INF);
    	root = 1;
    	tr[1].r = 2;
    	pushup(root);
    }
    
    //右旋
    void zig(int &p) {
    	int q = tr[p].l;
    	tr[p].l = tr[q].r, tr[q].r = p; p = q;
    	pushup(tr[p].r);
    	pushup(p);
    }
    
    //左旋
    void zag(int& p) {
    	int q = tr[p].r;
    	tr[p].r = tr[q].l;
    	tr[q].l = p; p = q;
    	pushup(tr[p].l); pushup(p);
    }
    
    void insert(int &p,int key) {
    	if (!p) p = get_node(key);
    	else if (tr[p].key == key) tr[p].cnt++;
    	else if (tr[p].key > key) {
    		insert(tr[p].l, key);
    		if (tr[tr[p].l].val > tr[p].val) zig(p);
    	}
    	else {
    		insert(tr[p].r,key);
    		if (tr[tr[p].r].val > tr[p].val) zag(p);
    	}
    	pushup(p);
    }
    
    void remove(int &p, int key) {
    	if (!p) return;
    	if (tr[p].key == key) {
    		if (tr[p].cnt > 1) tr[p].cnt--;
    		else if (tr[p].l || tr[p].r) {
    			if (!tr[p].r || tr[tr[p].l].val > tr[tr[p].r].val) {
    				zig(p);
    				remove(tr[p].r, key);
    			}
    			else {
    				zag(p);
    				remove(tr[p].l, key);
    			}
    		}
    		else p = 0;
    	}
    	else if (tr[p].key > key) {
    		remove(tr[p].l, key);
    	}
    	else {
    		remove(tr[p].r, key);
    	}
    	pushup(p);
    }
    
    int get_rank_by_key(int& p, int key) {
    	if (!p) return 0;
    	if (tr[p].key == key) return tr[tr[p].l].size + 1;
    	if (tr[p].key > key) return get_rank_by_key(tr[p].l,key);
    	return tr[tr[p].l].size + tr[p].cnt + get_rank_by_key(tr[p].r,key);
    	return 0;
    }
    
    
    int get_key_by_rank(int& p, int rank) {
    	if (!p) return INF;
    	if (tr[tr[p].l].size >= rank) return get_key_by_rank(tr[p].l,rank);
    	if (tr[tr[p].l].size + tr[p].cnt >= rank) return tr[p].key;
    	return get_key_by_rank(tr[p].r,rank-tr[tr[p].l].size-tr[p].cnt);
    	return 0;
    }
    
    
    
    
    int get_prev(int& p, int key) {
    	if (!p)  return -INF;
    	if (tr[p].key >= key)return get_prev(tr[p].l,key);
    	return max(tr[p].key,get_prev(tr[p].r,key));
    
    	return 0;
    }
    
    
    
    int get_next(int& p, int key) {
    	if (!p) return INF;
    	if (tr[p].key <= key) return get_next(tr[p].r, key);
    	return min(tr[p].key, get_next(tr[p].l,key));
    
    	return 0;
    }
    
    
    
    int main()
    {
    	build();
    
    	cin >> n;
    	while (n--) {
    		int opt, x;
    		cin >> opt>>x;
    		if (opt == 1) {
    			insert(root,x);
    		}
    		else if (opt == 2) {
    			remove(root,x);
    		}
    		else if (opt == 3) {
    			cout << get_rank_by_key(root,x)-1<<endl;
    		}
    		else if (opt == 4) {
    			cout << get_key_by_rank(root,x+1)<< endl;
    		}
    		else if (opt == 5) {
    			cout << get_prev(root, x) <<  endl;
    		}
    		else if (opt == 6) {
    			cout << get_next(root, x) << endl;
    		}
    	}
    
    
    	return 0;
    }
    

    我的视频题解空间

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    第一节:SpringMVC概述
    SpringMVC【目录】
    Windows 系统快速查看文件MD5
    (error) ERR wrong number of arguments for 'hmset' command
    hive使用遇到的问题 cannot recognize input
    Overleaf支持的部分中文字体预览
    Understanding and Improving Fast Adversarial Training
    Django2实战示例 第十三章 上线
    Django2实战示例 第十二章 创建API
    Django2实战示例 第十一章 渲染和缓存课程内容
  • 原文地址:https://www.cnblogs.com/itdef/p/15450434.html
Copyright © 2011-2022 走看看