[Bzoj3224][Tyvj1728] 普通平衡树(splay/无旋Treap)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224

平衡树入门题,学习学习。

splay(学习yyb巨佬)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const int maxn = 500100;
  5 const int INF = 1e9;
  6 inline void read(int &n) {
  7     register int x = 0, t = 1;
  8     register char ch = getchar();
  9     while (ch != '-' && (ch<'0' || ch>'9'))ch = getchar();
 10     if (ch == '-') { t = -1; ch = getchar(); }
 11     while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
 12     n = x * t;
 13 }
 14 int root, len;
 15 struct node {
 16     int fa;//节点的父节点
 17     int siz;//节点的子树数量
 18     int ch[2];//节点的左(0)子节点和右(1)子节点
 19     int val;//节点的值
 20     int num;//节点的值的数量
 21 }a[maxn];
 22 inline void pushup(int x) {//更新当前节点的子树//当前子树的大小是左子树大小加上右子树大小当前当前节点个数
 23     a[x].siz = a[a[x].ch[0]].siz + a[a[x].ch[1]].siz + a[x].num;
 24 }
 25 inline void rotate(int x) {//旋转操作//将x旋转到x的父亲的位置
 26     int y = a[x].fa;//y是x的父节点
 27     int z = a[y].fa;//z是x的祖父节点
 28     int k = (a[y].ch[1] == x);//求x是y的左(0)还是右(1)节点
 29     a[z].ch[a[z].ch[1] == y] = x;//求y是z的左(0)还是右(1)节点,同时将x放在该位置
 30     a[x].fa = z;//修改x的父节点
 31     a[y].ch[k] = a[x].ch[k ^ 1];//把x的儿子给y
 32     a[a[x].ch[k ^ 1]].fa = y;//更新父节点为y
 33     a[x].ch[k ^ 1] = y;//y变为x的子节点
 34     a[y].fa = x;//y的父亲更新为x
 35     pushup(y), pushup(x);//更新y和x的子节点数量
 36 }
 37 inline void splay(int x, int goal) {//将x旋转为goal的子节点
 38     while (a[x].fa != goal) {
 39         int y = a[x].fa;
 40         int z = a[y].fa;
 41         if (z != goal)
 42             (a[y].ch[1] == x) ^ (a[z].ch[1] == y) ? rotate(x) : rotate(y);
 43         //如果x和y同为左儿子或者右儿子先旋转y
 44         //如果x和y不同为左儿子或者右儿子先旋转x
 45         //如果不双旋的话,旋转完成之后树的结构不会变化
 46         rotate(x);
 47     }
 48     if (goal == 0)
 49         root = x;
 50 }
 51 inline void insert(int x) {
 52     int now = root, fa = 0;//当前节点now和now的父节点fa
 53     while (now&&a[now].val != x) {//当now存在并且没有移动到当前的值
 54         fa = now;//父节点变为now
 55         now = a[now].ch[x > a[now].val];//x大于当前位置则now向右,否则now向左
 56     }
 57     if (now)//这个值出现过
 58         a[now].num++;//值增加
 59     else {//这个值第一次出现,要新建一个节点来存放
 60         now = ++len;
 61         if (fa)//父节点不是根节点(0)
 62             a[fa].ch[x > a[fa].val] = now;
 63         //初始化节点
 64         a[now].ch[0] = a[now].ch[1] = 0;
 65         a[now].siz = 1;
 66         a[now].num = 1;
 67         a[now].fa = fa;
 68         a[now].val = x;
 69     }
 70     splay(now, 0);
 71 }
 72 inline void  Find(int x) {//查找x的位置,并将其旋转到根节点
 73     int now = root;
 74     if (!now)return;//数为空
 75     while (a[now].ch[x > a[now].val] && x != a[now].val)////当存在儿子并且当前位置的值不等于x
 76         now = a[now].ch[x > a[now].val];
 77     splay(now, 0);//把当前位置旋转到根节点
 78 }
 79 inline int Next(int x, int flag) {//查找x的前驱(0)或者后继(1)
 80     Find(x);
 81     int now = root;
 82     if (a[now].val > x&&flag)return now;//如果当前节点的值大于x并且要查找的是后继
 83     if (a[now].val < x && !flag)return now;//如果当前节点的值小于x并且要查找的是前驱
 84     now = a[now].ch[flag];//查找后继的话在右儿子上找,前驱在左儿子上找
 85     while (a[now].ch[flag ^ 1])now = a[now].ch[flag ^ 1];
 86     return now;
 87 }
 88 inline void Delete(int x) {//删除一个x
 89     int last = Next(x, 0);//查找x的前驱
 90     int next = Next(x, 1);//查找x的后继
 91     splay(last, 0), splay(next, last);
 92     //将前驱旋转到根节点,后继旋转到根节点下面
 93     //很明显,此时后继是前驱的右儿子,x是后继的左儿子,并且x是叶子节点
 94     int now = a[next].ch[0];//后继的左儿子,也就是x
 95     if (a[now].num > 1) {//超过一个就删除一个
 96         a[now].num--;
 97         splay(now, 0);
 98     }
 99     else
100         a[next].ch[0] = 0;//直接删除
101 
102 }
103 inline int kth(int k) {//查找第k小的数
104     int now = root;
105     if (a[now].siz < k)
106         return 0;
107     while (1) {
108         int y = a[now].ch[0];//y是左儿子
109         if (k > a[y].siz + a[now].num) {//如果排名比左儿子的大小和当前节点的数量要大
110             k -= a[y].siz + a[now].num;//排名减小
111             now = a[now].ch[1];//定在右儿子上找
112         }
113         else {
114             if (k <= a[y].siz)
115                 now = y;
116             else
117                 return a[now].val;
118         }
119     }
120 }
121 int main() {
122     int n;
123     read(n);
124     root = 0, len = 0;
125     insert(1000000000);
126     insert(-1000000000);
127     while (n--) {
128         int q, x;
129         read(q), read(x);
130         if (q == 1)
131             insert(x);
132         else if (q == 2)
133             Delete(x);
134         else if (q == 3) {
135             Find(x);
136             printf("%d\n", a[a[root].ch[0]].siz);
137         }
138         else if (q == 4)
139             printf("%d\n", kth(x + 1));
140         else if (q == 5)
141             printf("%d\n", a[Next(x, 0)].val);
142         else if (q == 6)
143             printf("%d\n", a[Next(x, 1)].val);
144     }
145 }

无旋Treap(学习fzszkl巨佬)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const int maxn = 1e5 + 10;
  5 int Siz[maxn], ls[maxn], rs[maxn], val[maxn], pos[maxn], root;
  6 int cnt;
  7 int send = 19260817;
  8 inline int Rand() {
  9     send ^= send << 7;
 10     send ^= send >> 5;
 11     send ^= send << 13;
 12     return send;
 13 }
 14 inline int New(int x) {
 15     cnt++;
 16     pos[cnt] = Rand();
 17     Siz[cnt] = 1;
 18     val[cnt] = x;
 19     return cnt;
 20 }
 21 inline void up(int x) {
 22     Siz[x] = Siz[ls[x]] + Siz[rs[x]] + 1;
 23 }
 24 void split_size(int x, int siz, int &A, int &B) {
 25     if (x == 0)return (void)(A = B = 0);
 26     if (siz <= Siz[ls[x]])
 27         B = x, split_size(ls[x], siz, A, ls[x]);
 28     else
 29         A = x, split_size(rs[x], siz - Siz[ls[x]] - 1, rs[x], B);
 30     up(x);
 31 }
 32 void split_val(int x, int v, int &A, int &B) {
 33     if (x == 0)return (void)(A = B = 0);
 34     if (v < val[x])
 35         B = x, split_val(ls[x], v, A, ls[x]);
 36     else
 37         A = x, split_val(rs[x], v, rs[x], B);
 38     up(x);
 39 }
 40 int Merge(int A, int B) {
 41     if (A == 0 || B == 0)return A | B;
 42     int ans;
 43     if (pos[A] > pos[B])ans = A, rs[A] = Merge(rs[A], B);
 44     else ans = B, ls[B] = Merge(A, ls[B]);
 45     up(ans);
 46     return ans;
 47 }
 48 void dfs(int x) {
 49     if (x == 0)
 50         return;
 51     printf("%d ", x);
 52     dfs(ls[x]);
 53     dfs(rs[x]);
 54 }
 55 void insert(int x) {
 56     int A, B;
 57     split_val(root, x - 1, A, B);
 58     root = Merge(Merge(A, New(x)), B);
 59 }
 60 void Delete(int x) {
 61     int A, B, C, D;
 62     split_val(root, x - 1, A, B);
 63     split_size(B, 1, C, D);//C就是删除的节点
 64     root = Merge(A, D);
 65 }
 66 int Rank(int x) {//查x的排名
 67     int A, B, ans;
 68     split_val(root, x - 1, A, B);
 69     ans = Siz[A] + 1;
 70     root = Merge(A, B);
 71     return ans;
 72 }
 73 int getR(int x) {//查第x名是什么
 74     int A, B, C, D, ans;
 75     split_size(root, x - 1, A, B);
 76     split_size(B, 1, C, D);
 77     ans = val[C];
 78     Merge(Merge(A, C), D);
 79     return ans;
 80 }
 81 int last(int x) {
 82     int A, B, C, D, ans;
 83     split_val(root, x - 1, A, B);
 84     split_size(A, Siz[A] - 1, C, D);
 85     ans = val[D];
 86     Merge(Merge(C, D), B);
 87     return ans;
 88 }
 89 int Next(int x) {
 90     int A, B, C, D, Ans;
 91     split_val(root, x, A, B);
 92     split_size(B, 1, C, D);
 93     Ans = val[C];
 94     root = Merge(Merge(A, C), D);
 95     return Ans;
 96 }
 97 int main() {
 98     int n;
 99     scanf("%d", &n);
100     while (n--) {
101         int opt, x;
102         scanf("%d%d", &opt, &x);
103         if (opt == 1)
104             insert(x);
105         else if (opt == 2)
106             Delete(x);
107         else if (opt == 3)
108             printf("%d\n", Rank(x));
109         else if (opt == 4)
110             printf("%d\n", getR(x));
111         else if (opt == 5)
112             printf("%d\n", last(x));
113         else if (opt == 6)
114             printf("%d\n", Next(x));
115     }
116     return 0;
117 }

 

posted @ 2019-07-02 11:14  祈梦生  阅读(148)  评论(0编辑  收藏  举报