日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Treap模板

發布時間:2023/12/3 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Treap模板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

打ACM這么久了,竟然還不會寫平衡樹,趁寒假有時間趕緊學一波,聽說有個叫Treap的實現起來比較簡單。

聲明

struct node{int key,prio,sz;int ch[2]; }treap[maxn]; //key是存儲在節點內部有意義的值 //prio是隨機優先權,用于平衡樹堆 //sz表示該節點子樹的大小 int tot,root; //tot表示節點池使用情況 //root表示一顆Treap的根

旋轉操作

void rotate(int &rt,bool d){//d為旋轉方向:0向左,1向右int x = rt;rt = treap[rt].ch[!d];treap[x].ch[!d] = treap[rt].ch[d];treap[rt].ch[d] = x;treap[x].sz = treap[treap[x].ch[0]].sz + 1 + treap[treap[x].ch[1]].sz;treap[rt].sz = treap[treap[rt].ch[0]].sz + 1 + treap[treap[rt].ch[1]].sz; }

隨機數算法

int randint(){static int seed = 703;return seed = int(seed*48271LL%2147483647); } //這樣可以不重復的取遍int類型的隨機數

插入

void ins(int &rt,int key){if(!rt) { //插入到目標處則新建一個節點rt = ++tot;treap[rt].key = key;treap[rt].prio = randint();treap[rt].sz = 1;}else{bool d = key > treap[rt].key; //目標方向ins(treap[rt].ch[d],key);treap[rt].sz ++;if(treap[rt].prio < treap[treap[rt].ch[d]].prio)rotate(rt,!d); //根據優先權進行旋轉 } }

刪除

//刪除值為key的1個節點,若成功返回true bool erase(int &rt,int key){if(!rt) return false; if(key != treap[rt].key){if(erase(treap[rt].ch[key > treap[rt].key],key)){treap[rt].sz--;return true;}return false;}else if(treap[rt].ch[0] == 0) rt = treap[rt].ch[1];else if(treap[rt].ch[1] == 0) rt = treap[rt].ch[0];else{int &lft = treap[rt].ch[0],&rgt = treap[rt].ch[1];bool d = treap[lft].prio > treap[rgt].prio;rotate(rt,d);//遇見左右兒子都非空情況就將目標節點下傳,然后再刪除erase(treap[rt].ch[d],key);treap[rt].sz--;}return true; }

選kth小

//注意!該函數返回值為節點的編號!!! //想要獲得kth小節點的key值,采用引用傳值方法!!! int select(int rt,int kth,int &key){if(kth > treap[rt].sz || kth < 1) return 0;//如果找傳入數據kth非法則返回0for(int nums;rt;){nums = treap[treap[rt].ch[0]].sz+1;if(nums == kth){key = treap[rt].key;return rt;}else if(nums < kth){kth -= nums;rt = treap[rt].ch[1];}elsert = treap[rt].ch[0];}return rt; }

查元素x的rank

//注意!該函數的返回值也是節點編號,引用傳值的方式返回rank //該函數用于找到第一個節點值.key >= key的節點,并返回 //類似于lower_bound int getrank(int rt,int key,int &rank){int pre = 0,nums = 0,d;rank = 0;while(1){if(treap[rt].key >= key) pre = rt,rank = nums+treap[treap[rt].ch[0]].sz+1;d = key > treap[rt].key;if(!treap[rt].ch[d]) break;if(d) nums += treap[treap[rt].ch[0]].sz+1;rt = treap[rt].ch[d];}if(!pre) pre = rt,rank = nums+1+treap[treap[rt].ch[0]].sz;return pre; }

小結

還是要多熟練,自己多動手寫一寫,用起來才會更加得心應手一些。 還有數的前驅和后繼都可以用select和getrank組合,請讀者手動實現。

起碼會寫一種平衡樹了,不是嗎?

總結

以上是生活随笔為你收集整理的Treap模板的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。