【code】Splay 模板
生活随笔
收集整理的這篇文章主要介紹了
【code】Splay 模板
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;// Splay
class Splay{#define root T[0].son[1] //T[0]為超級根,樹根為超級根的右孩子private:struct Tree{ //一個節點只存儲一個數值,一個數值只由一個點存儲int fa, son[2]/*0 左,1 右*/, v/*當前節點數值*/, sum/*以當前節點為根的樹中所有數值的數量*/, recy/*當前點的數值的數量*/;}T[100005];int ctp/*數值數量*/, ctn/*節點編號*/;void update(int k){ //更新sumT[k].sum = T[T[k].son[1]].sum+T[T[k].son[0]].sum+T[k].recy;}int identify(int k){ //識別自己是左(右)孩子return T[T[k].fa].son[0]==k?0:1;}void connect(int s, int f, int lr){ //建立兩點間父子關系T[s].fa = f, T[f].son[lr] = s;}void rotate(int k){ //左(右)旋操作int p = T[k].fa, q = T[p].fa;int lrk = identify(k), lrp = identify(p);int b = T[k].son[lrk^1];connect(b, p, lrk), connect(p, k, lrk^1), connect(k, q, lrp);update(p), update(k);}void splay(int k, int to){ //核心 將點 k 旋轉到點 toto = T[to].fa; int up;while(T[k].fa != to){up = T[k].fa;if(T[up].fa == to) rotate(k);else{identify(k)==identify(up)?rotate(up):rotate(k);rotate(k);}}}int creat(int v, int fa){ //新建點T[++ctn].fa = fa, T[ctn].v = v;T[ctn].sum = T[ctn].recy = 1;return ctn;}void destory(int k){ //摧毀點T[k].fa = T[k].sum = T[k].son[1] = T[k].son[0] = T[k].recy = 0;}int find(int v){ //查找點int k = root, next;while(T[k].v != v){next = v<T[k].v?0:1;if(!T[k].son[next]) return 0;k = T[k].son[next];}splay(k, root);return k;}int build(int v){ //沒有splay的push(見下方push)if(!ctp++){root = creat(v, 0);return 0;}int k = root, next;while(T[k].v != v){T[k].sum++;next = v<T[k].v?0:1;if(!T[k].son[next]) return T[k].son[next] = creat(v, k);k = T[k].son[next];}T[k].sum++;T[k].recy++;return k;}public:void push(int v){ //插入一個數值splay(build(v), root);}void pop(int v){ //刪除一個數值int k = find(v);if(!k) return;ctp--;if(T[k].recy > 1){T[k].recy--;T[k].sum--;return;}if(!T[k].son[0]) connect(T[k].son[1], 0, 1);else if(!T[k].son[1]) connect(T[k].son[0], 0, 1);else{int ls = T[k].son[0];while(T[ls].son[1]) ls = T[ls].son[1];splay(ls, T[k].son[0]);int rs = T[k].son[1];connect(rs, ls, 1), connect(ls, 0, 1);update(ls);}destory(k);}int rank(int v){ //查詢數值 v 的排名int k = root, ans = 0;if(!root) return 0;while(T[k].v != v){if(v < T[k].v) k = T[k].son[0];else{ans += T[T[k].son[0]].sum+T[k].recy;k = T[k].son[1];}if(!k) return 0;}ans += T[T[k].son[0]].sum+1;splay(k, root);return ans;}int atrank(int x){ //查詢排名為 x 的數值if(x > ctp) return -INF;int k = root, p;while(1){p = T[T[k].son[0]].sum+T[k].recy;if(x>T[T[k].son[0]].sum && x<=p) break;if(x < p) k = T[k].son[0];else{x -= p;k = T[k].son[1];} }splay(k, root);return T[k].v;}int upper(int v){ //查詢數值 v 的后繼int k = root, ans = INF;while(k){if(T[k].v>v && T[k].v<ans) ans = T[k].v;if(v < T[k].v) k = T[k].son[0];else k = T[k].son[1];}return ans;}int lower(int v){ //查詢數值 v 的前驅int k = root, ans = -INF;while(k){if(T[k].v<v && T[k].v>ans) ans = T[k].v;if(v > T[k].v) k = T[k].son[1];else k = T[k].son[0];}return ans;}#undef root
}W;// main
int main(){int n, a, b;scanf("%d", &n);while(n--){scanf("%d%d", &a, &b);if(a == 1) W.push(b);else if(a == 2) W.pop(b);else if(a == 3) printf("%d\n", W.rank(b));else if(a == 4) printf("%d\n", W.atrank(b));else if(a == 5) printf("%d\n", W.lower(b));else printf("%d\n", W.upper(b));}return 0;
}
轉載于:https://www.cnblogs.com/bosswnx/p/10570787.html
總結
以上是生活随笔為你收集整理的【code】Splay 模板的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MyEclipse自动补全
- 下一篇: 阿里云CentOS7.3搭建多用户私有g