P3369 【模板】普通平衡樹(treap)
題目:點選開啟連結
題意:中文題,不解釋。
分析:這題是平衡樹操作的裸題,用treap或者splay都行,我這裡用的是treap。treap入門推薦https://www.cnblogs.com/MyStringIsNotNull/p/9165675.html,寫的非常詳細,程式碼參考https://www.cnblogs.com/candy99/p/6105347.html。
程式碼:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<unordered_map>
#include<unordered_set>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<complex>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iomanip>
#include<string>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cctype>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<map>
using namespace std;
#define pt(a) cout<<a<<endl
#define debug test
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
typedef pair<int,int> PII;
const ll mod = 1e9+7;
const int N = 1e6+10;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qp(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int to[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct node{
int l,r,size,v,w,rnd;///左、右子樹、包含本節點的子樹大小、節點的值、節點值的數量、優先順序
}t[N];
int cnt,root;///節點個數、根
inline void update(int x){t[x].size=t[t[x].l].size+t[t[x].r].size+t[x].w;}///更新節點的子樹個數
inline void rturn(int &x){///左旋
int c=t[x].l;t[x].l=t[c].r;t[c].r=x;
t[c].size=t[x].size;update(x);x=c;
}
inline void lturn(int &x){///右旋
int c=t[x].r;t[x].r=t[c].l;t[c].l=x;
t[c].size=t[x].size;update(x);x=c;
}
void insert(int &x,int v){///插入
if(x==0){///空樹
cnt++;x=cnt;
t[cnt].l=t[cnt].r=0;
t[cnt].v=v;t[cnt].w=t[cnt].size=1;t[cnt].rnd=rand();
return;
}
t[x].size++;///子樹節點個數+1
if(t[x].v==v) t[x].w++;///節點值次數+1
else if(v<t[x].v){
insert(t[x].l,v);/// 遞迴左子樹
if(t[t[x].l].rnd<t[x].rnd) rturn(x);///插入後作出調整(右旋)
}else{
insert(t[x].r,v);/// 遞迴右子樹
if(t[t[x].r].rnd<t[x].rnd) lturn(x);///插入後作出調整(左旋)
}
}
void del(int &x,int v){///刪除值為x的數(若有多個相同的數,因只刪除一個)
if(x==0) return;///空樹 直接返回
if(t[x].v==v){
if(t[x].w>1){t[x].w--;t[x].size--;return;}///次數>1 次數-1 返回
if(t[x].l*t[x].r==0) x=t[x].l+t[x].r;///一個孩子為空,直接用另一個代替
else if(t[t[x].l].rnd<t[t[x].r].rnd)
rturn(x),del(x,v); ///右旋再繼續找
else lturn(x),del(x,v);///左旋再繼續找
}else {
t[x].size--;///節點值次數-1
if(v<t[x].v) del(t[x].l,v);///找左子樹
else del(t[x].r,v);///找右子樹
}
}
int rnk(int x,int v){///查詢數v的排名
if(x==0) return 0;///空樹 返回0
if(t[x].v==v) return t[t[x].l].size+1;///找到 返回
else if(v<t[x].v) return rnk(t[x].l,v);///繼續找左子樹
else return t[t[x].l].size+t[x].w+rnk(t[x].r,v);///+左子樹節點個數後 繼續找左子樹
}
int kth(int x,int k){///查詢排名為k的數
if(x==0) return 0;///空樹 返回0
if(k<=t[t[x].l].size) return kth(t[x].l,k);///左子樹節點個數大於k 繼續往左子樹找
else if(k>t[t[x].l].size+t[x].w)
return kth(t[x].r,k-t[t[x].l].size-t[x].w);///左子樹節點個數小於k 繼續往右子樹找
else return t[x].v;///找到 返回
}
int ans;
void pre(int x,int v){///查詢v的前驅
if(x==0) return;
if(v>t[x].v) ans=x,pre(t[x].r,v);///找到小於v的節點 往右子樹找
else pre(t[x].l,v);///否則往左子樹找
}
void suf(int x,int v){///查詢v的後繼
if(x==0) return;
if(v<t[x].v) ans=x,suf(t[x].l,v);///找到大於v的節點 往左子樹找
else suf(t[x].r,v);///否則往右子樹找
}
int n,op,x;
int main(){
srand(222);///隨機數種子
cin>>n;
while(n--){
cin>>op>>x;
if(op==1) insert(root,x);
else if(op==2) del(root,x);
else if(op==3) cout<<rnk(root,x)<<endl;
else if(op==4) cout<<kth(root,x)<<endl;
else if(op==5) ans=0,pre(root,x),cout<<t[ans].v<<endl;
else if(op==6) ans=0,suf(root,x),cout<<t[ans].v<<endl;
}
return 0;
}
相關文章
- P3369 【模板】普通平衡樹 —— Treap FHQtreapQT
- FHQ-Treap P3369 【模板】普通平衡樹
- 洛谷P3369 普通平衡樹(Splay)
- 洛谷P3369 普通平衡樹之板子
- P6136 【模板】普通平衡樹(資料加強版)
- [學習筆記] Splay & Treap 平衡樹 - 資料結構筆記資料結構
- FHQ-treap模板
- P3380 【模板】二逼平衡樹(樹套樹)
- P3391 【模板】文藝平衡樹
- P3391 【模板】文藝平衡樹(Splay)
- 普通平衡樹學習筆記之Splay演算法筆記演算法
- *衡樹 Treap(樹堆) 學習筆記筆記
- 平衡樹
- 文藝平衡樹
- 平衡查詢樹
- 平衡二叉樹二叉樹
- 平衡二叉樹,B樹,B+樹二叉樹
- 平衡樹學習筆記筆記
- 平衡樹 學習筆記筆記
- 平衡二叉樹(AVL)二叉樹
- 平衡樹和二叉樹的區別二叉樹
- 平衡二叉樹(AVL樹),原來如此!!!二叉樹
- 平衡二叉查詢樹:紅黑樹
- 十三、Mysql之平衡二叉樹(AVL樹)MySql二叉樹
- 主席樹模板
- 110. 平衡二叉樹二叉樹
- fhq-treap
- Java實現紅黑樹(平衡二叉樹)Java二叉樹
- 排序二叉樹和平衡二叉樹排序二叉樹
- 平衡二叉樹(AVL樹)和 二叉排序樹轉化為平衡二叉樹 及C語言實現二叉樹排序C語言
- 線段樹模板
- Treap——堆和二叉樹的完美結合,價效比極值的搜尋樹二叉樹
- 二叉堆、BST 與平衡樹
- LeetCode-110-平衡二叉樹LeetCode二叉樹
- JZ-039-平衡二叉樹二叉樹
- 手擼二叉樹——AVL平衡二叉樹二叉樹
- 自動平衡二叉樹的構建-AVL樹二叉樹
- BZOJ 3196 Tyvj 1730 二逼平衡樹:線段樹套splay