洛谷 P3369 模板普通平衡树(Treap/SBT)
Posted xgzc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P3369 模板普通平衡树(Treap/SBT)相关的知识,希望对你有一定的参考价值。
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入x数
- 删除x数(若有多个相同的数,因只删除一个)
- 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
- 查询排名为x的数
- 求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1≤opt≤6)
输出格式:
对于操作3,4,5,6每行输出一个数,表示对应答案
输入输出样例
输入样例:
10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598
输出样例:
106465 84185 492737
Splay 解析尚未完成 参见yyb dalao的博客
丑陋的代码送上(yyb大佬的代码比我的漂亮多了):
#ifndef SPLAY_TREE_HPP #define SPLAY_TREE_HPP #include<bits/stdc++.h> using namespace std; namespace Splay_tree { template<typename T> struct splay_node { T value; int size; int cnt; bool reverse; splay_node *father; splay_node *son[2]; splay_node(){} splay_node(T v, splay_node *f=NULL) :value(v),cnt(1) { father=f; size=0; son[0]=son[1]=NULL; } }; template<typename T, typename C=less<T> > class Splay { private: typedef splay_node<T> node; node *root; C small_to; bool big_to(T x, T y){return small_to(y,x);} bool equal_to(T x, T y){return !(small_to(x,y)||big_to(x,y));} inline bool son(node *f, node *s) { return f->son[1]==s; } inline void rotate(node *t) { node *f = t->father; node *g = f->father; bool a = son(f, t), b = !a; f->son[a] = t->son[b]; if (t->son[b] != NULL) t->son[b]->father = f; t->son[b] = f; f->father = t; t->father = g; if (g != NULL) g->son[son(g, f)] = t; else root = t; update(f); update(t); } inline void splay(node *t, node *p) { while (t->father != p) { node *f = t->father; node *g = f->father; if (g == p) rotate(t); else { if (son(g, f) ^ son(f, t)) rotate(t), rotate(t); else rotate(f), rotate(t); } } update(t); } inline T k_th(int k, node *f) { int tmp; node *t=root; while(1) { int tmp=size(t->son[0])+t->cnt; int sze=tmp-t->cnt; if(k<=tmp&&sze<k) break; else if(k<=sze) t=t->son[0]; else k-=tmp,t=t->son[1]; } T ans=t->value; return ans; } inline node* insert(T val, node *t) { int b=big_to(val,t->value); if(equal_to(val,t->value)) { t->cnt++; update(t); return t; } if(t->son[b]==NULL) { t->son[b]=new node(val,t); update(t->son[b]); update(t); return t->son[b]; } else { node *ans=insert(val,t->son[b]); update(t); return ans; } } public: Splay() { root=NULL; } inline void insert(T val) { if (root == NULL) { root = new node(val, NULL); update(root); return; } else { node *t = insert(val,root); splay(t,NULL); } } inline void erase(T val) { node *t = root; while(t) { if (equal_to(t->value,val)) break; t = t->son[big_to(val,t->value)]; } if (t != NULL) { splay(t, NULL); if(t->cnt>1) { t->cnt--; update(t); return; } if (t->son[0] == NULL) { root = t->son[1]; if (root != NULL) { root->father = NULL; update(root); } } else { node *p = t->son[0]; while (p->son[1] != NULL) p = p->son[1]; splay(p, t); root = p; root->father = NULL; p->son[1] = t->son[1]; update(p); if (p->son[1] != NULL) p->son[1]->father = p; } } } inline T pre(T val) { T ans=pre_ptr(val)->value; return ans; } inline T suc(T val) { node *x = root; insert(val); node *t=root->son[1]; if(t==NULL) return T(NULL); while(t->son[0]!=NULL) t=t->son[0]; erase(val); T ans=t->value; return ans; } inline T max_value() { node *t=root; while(t->son[1]!=NULL) t=t->son[1]; return t->value; } inline T min_value() { node *t=root; while(t->son[0]!=NULL) t=t->son[0]; return t->value; } inline T k_th(int k) { return k_th(k,NULL); } inline int rank(T val) { node *t=root; while(!equal_to(t->value, val)) t=t->son[big_to(val,t->value)]; splay(t,NULL); return size(t->son[0])+1; } inline void print() { print(root); puts(""); } private: inline node* pre_ptr(T val) { insert(val); node *t=root->son[0]; if(t==NULL) return NULL; while(t->son[1]!=NULL) t=t->son[1]; erase(val); return t; } inline void print(node *t) { if(t==NULL) return; print(t->son[0]); printf("%d ",t->value); print(t->son[1]); } inline int size(node *t) { return t == NULL ? 0 : t->size; } inline void update(node *t) { t->size = t->cnt; t->size += size(t->son[0]); t->size += size(t->son[1]); } }; } #endif int main() { using namespace Splay_tree; int n; Splay<int> tree; scanf("%d",&n); for(int i=1;i<=n;i++) { int ops; int x; scanf("%d%d",&ops,&x); switch(ops) { case 1: tree.insert(x); break; case 2: tree.erase(x); break; case 3: { int t=tree.rank(x); printf("%d\\n",t); break; } case 4: { int y=tree.k_th(x); printf("%d\\n",y); break; } case 5: printf("%d\\n",tree.pre(x)); break; case 6: int t=tree.suc(x); printf("%d\\n",t); break; } } }
以上是关于洛谷 P3369 模板普通平衡树(Treap/SBT)的主要内容,如果未能解决你的问题,请参考以下文章
洛谷P3369 模板普通平衡树(STL做法:vector&multiset)