首页 > 其他分享 >洛谷 P3369 【模板】普通平衡树

洛谷 P3369 【模板】普通平衡树

时间:2023-05-05 14:35:58浏览次数:35  
标签:ch 洛谷 cur val int siz P3369 return 模板

有旋Treap模板

#include <bits/stdc++.h>

using namespace std;

struct Node {
	Node *ch[2];
	int val, rank;
	int rep_cnt;
	int siz;

	Node(int val) : val(val), rep_cnt(1), siz(1) {
		ch[0] = ch[1] = nullptr;
		rank = rand();
	}

	void upd_siz() {
		siz = rep_cnt;
		if (ch[0] != nullptr) siz += ch[0]->siz;
		if (ch[1] != nullptr) siz += ch[1]->siz;
	}
};

enum rot_type {LF = 1, RT = 0};

void _rotate(Node *&cur, rot_type dir) {
	Node *tmp = cur->ch[dir];
	
	cur->ch[dir] = tmp->ch[!dir];
	tmp->ch[!dir] = cur;
	tmp->upd_siz();
	cur->upd_siz();
	cur = tmp;
}

void _insert(Node *&cur, int val) {
	if (cur == nullptr) {
		cur = new Node(val);
		return;
	}
	else if (cur->val == val) {
		cur->rep_cnt++;
		cur->siz++;
		return;
	}
	else if (cur->val > val) {
		_insert(cur->ch[0], val);
		if (cur->ch[0]->rank < cur->rank) {
			_rotate(cur, RT);
		}
		cur->upd_siz();
	}
	else if (cur->val < val) {
		_insert(cur->ch[1], val);
		if (cur->ch[1]->rank > cur->rank) {
			_rotate(cur, LF);
		}
		cur->upd_siz();
	}
}

void _del(Node *&cur, int val) {
	if (cur->val > val) {
		_del(cur->ch[0], val);
		cur->upd_siz();
	}
	else if (cur->val < val) {
		_del(cur->ch[1], val);
		cur->upd_siz();
	}
	else {
		if (cur->rep_cnt > 1) {
			cur->rep_cnt--;
			cur->siz--;
			return;
		}
		uint8_t state = 0;
		state |= (cur->ch[0] != nullptr);
		state |= ((cur->ch[1] != nullptr) << 1);
		//00:none	01:has left		10:has right	11:both
		Node *tmp = cur;
		switch(state) {
			case 0:
				delete cur;
				cur = nullptr;
				break;
			case 1:
				cur = tmp->ch[0];
				delete tmp;
				cur->upd_siz();
				break;
			case 2:
				cur = tmp->ch[1];
				delete tmp;
				cur->upd_siz();
				break;
			case 3:
				rot_type dir = cur->ch[0]->rank < cur->ch[1]->rank ? RT : LF;
				_rotate(cur, dir);
				_del(cur->ch[!dir], val);
				cur->upd_siz();
				break;
		}
	}
}

int _query_rank(Node *&cur, int val) {
	if (cur == nullptr) return 1;
	int less_siz = cur->ch[0] == nullptr ? 0 : cur->ch[0]->siz;
	if (val == cur->val) return less_siz + 1;
	else if (cur->val > val) {
		if (cur->ch[0] != nullptr) return _query_rank(cur->ch[0], val);
		else return 1;
	}
	else {
		if (cur->ch[1] != nullptr) return _query_rank(cur->ch[1], val) + less_siz + cur->rep_cnt;
		else return cur->siz + 1;
	}
}

int _query_val(Node *&cur, int rank) {
	if (cur == nullptr) return 0;
	int less_siz = cur->ch[0] == nullptr ? 0 : cur->ch[0]->siz;
	if (less_siz >= rank) return _query_val(cur->ch[0], rank);
	else if (less_siz + cur->rep_cnt >= rank) return cur->val;
	else return _query_val(cur->ch[1], rank - less_siz - cur->rep_cnt);
}

int q_pre_tmp;

int _query_prev(Node *cur, int val) {
	if (cur->val >= val) {
		if (cur->ch[0] != nullptr) return _query_prev(cur->ch[0], val); 
	}
	else {
		//we update the value of q_pre_tmp, only if we entered the else branch.
		q_pre_tmp = cur->val;
		if (cur->ch[1] != nullptr) _query_prev(cur->ch[1], val);
		return q_pre_tmp;		
		//we return the cur->val that entered the else branch the last time, wihch make sure that q_pre_tmp is the biggest valid value.
	}
	return -1;
}

int q_suf_tmp;

int _query_sufv(Node *cur, int val) {
	if (cur->val <= val) {
		if (cur->ch[1] != nullptr) return _query_sufv(cur->ch[1], val);
	}
	else {
		q_suf_tmp = cur->val;
		if (cur->ch[0] != nullptr) _query_sufv(cur->ch[0], val);
		return q_suf_tmp;
	}
	return -1;
}

int main() {
	int n;
	cin >> n;
	Node *root = nullptr;
	while (n--) {
		int op, x;
		cin >> op >> x;
		if (op == 1) _insert(root, x);
		if (op == 2) _del(root, x);
		if (op == 3) cout << _query_rank(root, x) << endl;
		if (op == 4) cout << _query_val(root, x) << endl;
		if (op == 5) cout << _query_prev(root, x) << endl;
		if (op == 6) cout << _query_sufv(root, x) << endl;
	}
	return 0;
}

标签:ch,洛谷,cur,val,int,siz,P3369,return,模板
From: https://www.cnblogs.com/lr599909928/p/17374038.html

相关文章

  • 模板方法中的线程安全问题
    1、线程安全?是否存在临界区,共享的变量,会被不同线程写入那么模板方法里面基类的成员变量或者方法就会存在线程安全问题2、excel  AbstractExcelSheet业务数据和excel逻辑解耦让data可以在service层之间set进来这样excel的相关类不用添加到spring容器中 pub......
  • 6-2 数组排序输出(函数模板)
    对于输入的每一批数,按从小到大排序后输出。一行输入为一批数,第一个输入为数据类型(1表示整数,2表示字符型数,3表示有一位小数的浮点数,4表示字符串,0表示输入结束),第二个输入为该批数的数量size(0<size<=10),接下来为size个指定类型的数据。输出将从小到大顺序输出数据。函数接口定义:sor......
  • 类模板。。。对象数组
    #include<bits/stdc++.h>usingnamespacestd;template<classT>classAAA{      Ta,b;   public:      AAA(T_a,T_b):a(_a),b(_b){};      Tsum(){         returna+b;      }      Tcha();};template<......
  • 洛谷P4824题解
    题面题意:给出字符串s和t,每次操作将s中出现的第一个t删去,直到不能删为止。求最后的串。|s|<=1e6题解:hash做法。(此题也有kmp和权值线段树做法)因为涉及到删除操作,所以我们要动态的实现这个过程。所以考虑开一个栈来存储当前留下的字符。然后每有一个字符入栈,就拿当前......
  • 洛谷P7469题解
    题面题意:有两个字符串a和b,问b中有多少个本质不同子串可以由a删除若干个字符得到。|a|,|b|<=3000题解:字典树(这个题做法很多,后补)。把字符串b的每个子串打到字典树上。然后因为3000^2*26这个东西比较大,所以不能用nxt[id][26]来存储,于是使用链式前向星存图,这样tri......
  • 极简爬虫通用模板
    网络爬虫的一般步骤如下:1、确定爬取目标:确定需要爬取的数据类型和来源网站。2、制定爬取策略:确定爬取哪些网页、如何爬取和频率等。3、构建爬虫程序:使用编程语言(如Python)实现爬虫程序,通过HTTP请求获取网页内容,并进行解析和处理。4、数据存储:将爬取到的数据存储到数据库或文件......
  • 5月4日:unordermap/set,哈希以及哈希常用的拉链法,开放地址法,以及模板的特化相关应用
    起处较为流行的数据储存方式为树形结构,再加上红黑树等优秀数据结构的发展,直到今天二叉平衡搜索树也经常被应用在各种方面,但是c++库里面还有两个与map/set很像的容器unorderedmap,他们的调用与普通的map几乎一样,有着非常优秀的查找时间复杂度,只是不能像二叉树哪样层序遍历得到顺序的......
  • 模板
    6-1有序数组(类模板)单位 福州大学实现一个类模板,它可以接受一组数据,能对数据排序,也能输出数组的内容。每行输入的第一个数字为0,1,2或3:为0时表示输入结束;为1时表示将输入整数,为2时表示将输入有一位小数的浮点数,为3时表示输入字符。如果第一个数字非0,则接下来将输入......
  • 打卡 有序数组(类模板)
    实现一个类模板,它可以接受一组数据,能对数据排序,也能输出数组的内容。每行输入的第一个数字为0,1,2或3:为0时表示输入结束;为1时表示将输入整数,为2时表示将输入有一位小数的浮点数,为3时表示输入字符。如果第一个数字非0,则接下来将输入一个正整数,表示即将输入的数据的数量。从每行......
  • 数组排序输出(函数模板)
    一、问题描述:对于输入的每一批数,按从小到大排序后输出。一行输入为一批数,第一个输入为数据类型(1表示整数,2表示字符型数,3表示有一位小数的浮点数,4表示字符串,0表示输入结束),第二个输入为该批数的数量size(0<size<=10),接下来为size个指定类型的数据。输出将从小到大顺序输出数据。函......