模板:无旋treap
生活随笔
收集整理的這篇文章主要介紹了
模板:无旋treap
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 前言
- 操作
- 合并
- 分裂
- 插入
- 刪除
- 查找第k大
- 查詢x的排名
- 前驅后繼
- 完整代碼
所謂無旋treap,就是不帶旋轉的treap
前言
現在“理論上”我會四種平衡樹了
之前說無旋treap功能弱,是我狗眼看銀低了qwq
這玩意區間上該搞的也能搞
而且確實是非常的 好寫!!
有點想把這個作為默認項了
嗚嗚嗚朝三暮四腫么辦吶
操作
關鍵是合并和分裂
合并
考慮合并u和v兩棵子樹
把優先級高的作為根
剩下的接著合并即可
分裂
給定一個val
<=val的歸一棵,>=val的歸另一棵
討論一些根歸誰
然后遞歸一下即可
如果要求前k個一棵是一個道理
插入
插入一個為v的元素
把樹按照v掰成兩個
把開的新點merge上去即可
刪除
刪除一個v
先把<=v的split出來
再把<v的split出來
剩下的全是=v的
把其左右子樹合并就相當于扣掉一個
最后merge回去就行
查找第k大
BST常規操作
il int findnth(int kth){//printf("findnth:%d\n",kth);int x=r;while(1){//printf("x=%d val=%d siz=%d ls=%d rs=%d\n",x,tr[x].val,tr[x].siz,tr[x].ls,tr[x].rs);if(kth<=tr[tr[x].ls].siz) x=tr[x].ls;else if(kth==tr[tr[x].ls].siz+1) return tr[x].val;else{kth-=tr[tr[x].ls].siz+1;x=tr[x].rs;}} }查詢x的排名
這個用常規的BST的操作是 不行 的!
因為樹上存在這權值相同的點
但可以直接把<x的split出來查詢siz
也很方便
最后記得要merge回去!
前驅后繼
BST典中典了屬于是
findnth(findrnk(x)-1)//前驅 findnth(findrnk(x+1))//后繼完整代碼
當然是普通平衡樹啦
#include<bits/stdc++.h> #define ll long long #define il inline using namespace std; const int N=1e6+100; const int M=2e6+100; ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();};while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f; } int n,m,s,t; struct node{int ls,rs,val,siz,key; }tr[N<<2]; int r,tot; il int New(int v){++tot;tr[tot].siz=1;tr[tot].ls=tr[tot].rs=0;tr[tot].key=rand();tr[tot].val=v;return tot; } il void pushup(int x){tr[x].siz=tr[tr[x].ls].siz+tr[tr[x].rs].siz+1;return; } il int merge(int u,int v){if(!u) return v;if(!v) return u;if(tr[u].key>tr[v].key){tr[u].rs=merge(tr[u].rs,v);pushup(u);return u;}else{tr[v].ls=merge(u,tr[v].ls);pushup(v);return v;} } il void split(int x,int v,int &L,int &R){if(!x){L=R=0;return;}if(tr[x].val<=v){L=x;split(tr[L].rs,v,tr[L].rs,R);pushup(L);}else{R=x;split(tr[R].ls,v,L,tr[R].ls);pushup(R);}return; } il int findnth(int kth){//printf("findnth:%d\n",kth);int x=r;while(1){//printf("x=%d val=%d siz=%d ls=%d rs=%d\n",x,tr[x].val,tr[x].siz,tr[x].ls,tr[x].rs);if(kth<=tr[tr[x].ls].siz) x=tr[x].ls;else if(kth==tr[tr[x].ls].siz+1) return tr[x].val;else{kth-=tr[tr[x].ls].siz+1;x=tr[x].rs;}} } il int findrnk(int v){int a(0),b(0),c(0),res;split(r,v-1,a,b);res=tr[a].siz;r=merge(a,b);return res+1; } il void ins(int v){int a(0),b(0),c(0);split(r,v,a,b);c=New(v);r=merge(merge(a,c),b);return; } il void del(int v){int a(0),b(0),c(0);split(r,v,a,b);split(a,v-1,a,c);r=merge(merge(a,merge(tr[c].ls,tr[c].rs)),b); } int main(){n=read();for(int i=1;i<=n;i++){int op=read(),x=read();switch(op){case 1:{ins(x);break;}case 2:{del(x);break;}case 3:{printf("%d\n",findrnk(x));break;}case 4:{printf("%d\n",findnth(x));break;}case 5:{printf("%d\n",findnth(findrnk(x)-1));break;}case 6:{printf("%d\n",findnth(findrnk(x+1)));break;}}}return 0; } /* */thanks for reading!
總結
以上是生活随笔為你收集整理的模板:无旋treap的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我想写篇日记如何在电脑上写日记
- 下一篇: LOJ洛谷P1248加工生产调度(贪心、