1. 程式人生 > >luogu3369 【模板】普通平衡樹(Treap/SBT)

luogu3369 【模板】普通平衡樹(Treap/SBT)

oid sin markdown 隨機 節點 nod -m rotate 編號

treap做法,參考hzwer的博客

#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
struct Node{
    int val, l, r, sze, rnd, hav;
    //val代表當前節點的值,l、r是左右孩子編號,sze是以當前節點為根的子樹的大小
    //rnd是一個隨機出來的權值, hav是當前節點的值對應的數字有幾個
}nd[100005];
int n, opt, x, rot, ans, num;
void update(int k){
    nd[k].sze = nd[nd[k].l].sze + nd[nd[k].r].sze + nd[k].hav;
}
void
lRotate(int &k){ int t=nd[k].r; nd[k].r = nd[t].l; nd[t].l = k; nd[t].sze = nd[k].sze; update(k); k = t; } void rRotate(int &k){ int t=nd[k].l; nd[k].l = nd[t].r; nd[t].r = k; nd[t].sze = nd[k].sze; update(k); k = t; } void ins(int &k, int x){ if(!k){ k = ++num; nd[k].sze = nd[k].hav = 1
; nd[k].val = x; nd[k].rnd = rand(); //創建一個新節點 return ; } nd[k].sze++; if(nd[k].val==x) nd[k].hav++; else if(x>nd[k].val){ ins(nd[k].r, x); if(nd[nd[k].r].rnd<nd[k].rnd) lRotate(k); //不滿足堆的性質則旋轉 } else{ ins(nd[k].l, x); if
(nd[nd[k].l].rnd<nd[k].rnd) rRotate(k); //不滿足堆的性質則旋轉 } } void del(int &k, int x){ if(!k) return ; if(nd[k].val==x){ if(nd[k].hav>1){ nd[k].hav--; nd[k].sze--; //要是有不止一個的話減一就好了 return ; } if(nd[k].l*nd[k].r==0) k = nd[k].l + nd[k].r; //如果左右子樹有一個為空,則把k置為不為空的那顆子樹 //如果均為空,那麽k也變成了空 else if(nd[nd[k].l].rnd<nd[nd[k].r].rnd) rRotate(k), del(k, x); else lRotate(k), del(k, x); } else if(x>nd[k].val) nd[k].sze--, del(nd[k].r, x); else nd[k].sze--, del(nd[k].l, x); } int queryRank(int k, int x){ if(!k) return 0; if(nd[k].val==x) return nd[nd[k].l].sze+1; else if(nd[k].val<x) return nd[nd[k].l].sze+nd[k].hav+queryRank(nd[k].r, x); else return queryRank(nd[k].l, x); } int queryNum(int k, int x){ if(!k) return 0; if(x<=nd[nd[k].l].sze) return queryNum(nd[k].l, x); else if(x>nd[nd[k].l].sze+nd[k].hav) return queryNum(nd[k].r, x-nd[nd[k].l].sze-nd[k].hav); else return nd[k].val; } void queryPre(int k, int x){ if(!k) return ; if(nd[k].val<x) ans = k, queryPre(nd[k].r, x); else queryPre(nd[k].l, x); } void queryNxt(int k, int x){ if(!k) return ; if(nd[k].val>x) ans = k, queryNxt(nd[k].l, x); else queryNxt(nd[k].r, x); } int main(){ cin>>n; while(n--){ scanf("%d %d", &opt, &x); if(opt==1) ins(rot, x); if(opt==2) del(rot, x); if(opt==3) printf("%d\n", queryRank(rot, x)); if(opt==4) printf("%d\n", queryNum(rot, x)); if(opt==5) queryPre(rot, x), printf("%d\n", nd[ans].val); if(opt==6) queryNxt(rot, x), printf("%d\n", nd[ans].val); } return 0; }

luogu3369 【模板】普通平衡樹(Treap/SBT)