# [BZOJ 3224]Tyvj 1728 普通平衡树

## Description

1. 插入x数
2. 删除x数(若有多个相同的数，因只删除一个)
3. 查询x数的排名(若有多个相同的数，因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x，且最大的数)
6. 求x的后继(后继定义为大于x，且最小的数)

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

106465
84185
492737

## HINT

1.n的数据范围：n<=100000
2.每个数的数据范围：[-2e9,2e9]

## 题解

### 1 Splay

#### 1.6 查找后继

  1 //It is made by Awson on 2017.11.28
2 #include <map>
3 #include <set>
4 #include <cmath>
5 #include <ctime>
6 #include <queue>
7 #include <stack>
8 #include <cstdio>
9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #define LL long long
16 #define Max(a, b) ((a) > (b) ? (a) : (b))
17 #define Min(a, b) ((a) < (b) ? (a) : (b))
18 using namespace std;
19 const int N = 100000;
20 const int INF = ~0u>>1;
21
22 struct Splay_tree {
23     int pre[N+5], ch[N+5][2], key[N+5], size[N+5], cnt[N+5], tot, root;
24     queue<int>mem;
25     void newnode(int &o, int keyy, int fa) {
26     if (!mem.empty()) o = mem.front(), mem.pop();
27     else o = ++tot;
28     pre[o] = fa, ch[o][0] = ch[o][1] = 0;
29     key[o] = keyy, cnt[o] = size[o] = 1;
30     }
31     void pushup(int o) {
32     size[o] = size[ch[o][0]]+size[ch[o][1]]+cnt[o];
33     }
34     void rotate(int o, int kind) {
35     int p = pre[o];
36     ch[p][!kind] = ch[o][kind], pre[ch[o][kind]] = p;
37     ch[pre[p]][ch[pre[p]][1] == p] = o, pre[o] = pre[p];
38     ch[o][kind] = p, pre[p] = o;
39     pushup(p), pushup(o);
40     }
41     void splay(int o, int goal) {
42     while (pre[o] != goal) {
43         if (pre[pre[o]] == goal) rotate(o, ch[pre[o]][0] == o);
44         else {
45         int p = pre[o], kind = ch[pre[p]][0] == p;
46         if (ch[p][kind] == o) rotate(o, !kind), rotate(o, kind);
47         else rotate(p, kind), rotate(o, kind);
48         }
49     }
50     if (goal == 0) root = o;
51     }
52     void insert(int &o, int keyy, int fa) {
53     if (o == 0) {
54         newnode(o, keyy, fa); splay(o, 0); return;
55     }
56     size[o]++;
57     if (key[o] == keyy) {
58         cnt[o]++; splay(o, 0); return;
59     }
60     insert(ch[o][keyy > key[o]], keyy, o);
61     }
62     void find(int o, int keyy) {
63     if (o == 0) return;
64     if (key[o] == keyy) {
65         splay(o, 0); return;
66     }
67     if (ch[o][keyy > key[o]]) find(ch[o][keyy > key[o]], keyy);
68     else splay(o, 0);
69     }
70     int get_las(int keyy) {
71     find(root, keyy);
72     if (keyy > key[root]) return root;
73     int u = ch[root][0];
74     while (ch[u][1]) u = ch[u][1];
75     return u;
76     }
77     int get_nex(int keyy) {
78     find(root, keyy);
79     if (keyy < key[root]) return root;
80     int u = ch[root][1];
81     while (ch[u][0]) u = ch[u][0];
82     return u;
83     }
84     void delet(int keyy) {
85     int las = get_las(keyy);
86     int nex = get_nex(keyy);
87     splay(las, 0), splay(nex, las);
88     size[las]--, size[nex]--;
89     if (cnt[ch[nex][0]] > 1) {
90         cnt[ch[nex][0]]--; size[ch[nex][0]]--;
91         splay(ch[nex][0], 0);
92     }else {
93         mem.push(ch[nex][0]);
94         ch[nex][0] = 0;
95     }
96     }
97     int Kth(int o, int rest) {
98     if (rest >= size[ch[o][0]]+1 && rest <= size[ch[o][0]]+cnt[o]) return o;
99     if (rest > size[ch[o][0]]+cnt[o]) return Kth(ch[o][1], rest-size[ch[o][0]]-cnt[o]);
100     return Kth(ch[o][0], rest);
101     }
102 }S;
103 int n, opt, x;
104
105 void work() {
106     S.insert(S.root, INF, 0);
107     S.insert(S.root, -INF, 0);
108     scanf("%d", &n);
109     while (n--) {
110     scanf("%d%d", &opt, &x);
111     if (opt == 1) S.insert(S.root, x, 0);
112     else if (opt == 2) S.delet(x);
113     else if (opt == 3) {
114         S.find(S.root, x);
115         printf("%d\n", S.size[S.ch[S.root][0]]);
116     }else if (opt == 4) printf("%d\n", S.key[S.Kth(S.root, x+1)]);
117     else if (opt == 5) printf("%d\n", S.key[S.get_las(x)]);
118     else if (opt == 6) printf("%d\n", S.key[S.get_nex(x)]);
119     }
120 }
121 int main() {
122     work();
123     return 0;
124 }
Splay

### 2 替罪羊树

  1 //It is made by Awson on 2017.12.8
2 #include <map>
3 #include <set>
4 #include <cmath>
5 #include <ctime>
6 #include <queue>
7 #include <stack>
8 #include <cstdio>
9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #define LL long long
16 #define Max(a, b) ((a) > (b) ? (a) : (b))
17 #define Min(a, b) ((a) < (b) ? (a) : (b))
18 using namespace std;
19 const int N = 100000;
20 const int INF = ~0u>>1;
21 const double alpha = 0.75;
22
23 struct Scapegoat_tree {
24     int size[N+5], ch[N+5][2], key[N+5], del[N+5], pre[N+5], root, tot, tmp[N+5];
25     queue<int>mem;
26     void newnode(int &o, int keyy, int fa) {
27     if (!mem.empty()) o = mem.front(), mem.pop();
28     else o = ++tot;
29     size[o] = 1, ch[o][0] = ch[o][1] = del[o] = 0;
30     key[o] = keyy, pre[o] = fa;
31     }
32     bool balance(int o) {
33     return size[o]*alpha >= size[ch[o][0]] && size[o]*alpha >= size[ch[o][1]];
34     }
35     void pushup(int o) {
36     size[o] = size[ch[o][0]]+size[ch[o][1]]+(!del[o]);
37     }
38     void travel(int o, int &pos) {
39     if (ch[o][0]) travel(ch[o][0], pos);
40     if (!del[o]) tmp[++pos] = o;
41     else mem.push(o);
42     if (ch[o][1]) travel(ch[o][1], pos);
43     }
44     int device(int fa, int l, int r) {
45     if (l > r) return 0;
46     int mid = (l+r)>>1, o = tmp[mid];
47     ch[o][0] = device(o, l, mid-1);
48     ch[o][1] = device(o, mid+1, r);
49     pre[o] = fa; size[o] = 1;
50     pushup(o);
51     return o;
52     }
53     void rebuild(int o) {
54     int pos = 0; travel(o, pos);
55     if (root == o) root = device(0, 1, pos);
56     else {
57         int t = ch[pre[o]][1] == o;
58         ch[pre[o]][t] = device(pre[o], 1, pos);
59     }
60     }
61     int Insert(int &o, int keyy, int fa) {
62     if (!o) {
63         newnode(o, keyy, fa); return 0;
64     }
65     size[o]++;
66     int p = Insert(ch[o][keyy >= key[o]], keyy, o);
67     if (!balance(o)) p = o;
68     return p;
69     }
70     void insert(int &o, int keyy, int fa) {
71     int x = Insert(o, keyy, fa); if (x) rebuild(x);
72     }
73     int rank(int o, int keyy) {
74     if (!o) return 1;
75     if (key[o] < keyy) return size[ch[o][0]]+(!del[o])+rank(ch[o][1], keyy);
76     else return rank(ch[o][0], keyy);
77     }
78     int Erase(int o, int rank) {
79     size[o]--;
80     if (!del[o] && size[ch[o][0]]+(!del[o]) == rank) {
81         del[o] = 1; return 0;
82     }
83     int p;
84     if (size[ch[o][0]] >= rank) p = Erase(ch[o][0], rank);
85     else p = Erase(ch[o][1], rank-(size[ch[o][0]]+(!del[o])));
86     if (!balance(o)) p = o;
87     return p;
88     }
89     void erase(int o, int keyy) {
90     int rk = rank(o, keyy);
91     int x = Erase(o, rk); if (x) rebuild(x);
92     }
93     int get_num(int o, int rank) {
94     if (!del[o] && size[ch[o][0]]+(!del[o]) == rank) return key[o];
95     if (size[ch[o][0]] >= rank) return get_num(ch[o][0], rank);
96     return get_num(ch[o][1], rank-(size[ch[o][0]]+(!del[o])));
97     }
98 }S;
99 int n, opt, x;
100
101 void work() {
102     S.insert(S.root, INF, 0);
103     S.insert(S.root, -INF, 0);
104     scanf("%d", &n);
105     while (n--) {
106     scanf("%d%d", &opt, &x);
107     if (opt == 1) S.insert(S.root, x, 0);
108     else if (opt == 2) S.erase(S.root, x);
109     else if (opt == 3) printf("%d\n", S.rank(S.root, x)-1);
110     else if (opt == 4) printf("%d\n", S.get_num(S.root, x+1));
111     else if (opt == 5) printf("%d\n", S.get_num(S.root, S.rank(S.root, x)-1));
112     else printf("%d\n", S.get_num(S.root, S.rank(S.root, x+1)));
113     }
114 }
115 int main() {
116     work();
117     return 0;
118 }
Scapegoat

### 3 Treap

$Treap$的平衡是基于堆性质的。它的$key$值满足$BST$的性质，平衡参数$lev$满足堆性质。

  1 //It is made by Awson on 2017.12.11
2 #include <map>
3 #include <set>
4 #include <cmath>
5 #include <ctime>
6 #include <queue>
7 #include <stack>
8 #include <cstdio>
9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #define LL long long
16 #define Max(a, b) ((a) > (b) ? (a) : (b))
17 #define Min(a, b) ((a) < (b) ? (a) : (b))
18 using namespace std;
19 const int N = 100000;
20 const int INF = ~0u>>1;
21
22 struct Treap {
23     int ch[N+5][2], lev[N+5], size[N+5], cnt[N+5], key[N+5], tot, root;
24     queue<int>mem;
25     void newnode(int &o, int keyy) {
26     if (!mem.empty()) o = mem.front(), mem.pop();
27     else o = ++tot;
28     ch[o][0] = ch[o][1] = 0;
29     cnt[o] = size[o] = 1;
30     key[o] = keyy, lev[o] = rand();
31     }
32     void pushup(int o) {
33     size[o] = size[ch[o][0]]+size[ch[o][1]]+cnt[o];
34     }
35     void rotate(int &o, int kind) {
36     int x = ch[o][!kind];
37     ch[o][!kind] = ch[x][kind];
38     ch[x][kind] = o;
39     o = x;
40     }
41     void insert(int &o, int keyy) {
42     if (!o) {
43         newnode(o, keyy); return;
44     }
45     size[o]++;
46     if (key[o] == keyy) {
47         cnt[o]++; return;
48     }
49     int kind = keyy >= key[o];
50     insert(ch[o][kind], keyy);
51     if (lev[ch[o][kind]] > lev[o]) {
52         rotate(o, !kind); pushup(ch[o][!kind]), pushup(o);
53     }
54     }
55     void delet(int &o, int keyy) {
56     if (key[o] == keyy) {
57         if (cnt[o] > 1) {
58         size[o]--; cnt[o]--; return;
59         }else {
60         if (ch[o][0] && ch[o][1]) {
61             int kind = lev[ch[o][0]] > lev[ch[o][1]];
62             rotate(o, kind); pushup(ch[o][kind]), pushup(o);
63             size[o]--;
64             delet(ch[o][kind], keyy);
65         }else {
66             int kind = (bool)ch[o][1];
67             mem.push(o);
68             o = ch[o][kind];
69         }
70         }
71     }else {
72         size[o]--; delet(ch[o][keyy >= key[o]], keyy);
73     }
74     }
75     int rank(int o, int keyy) {
76     if (key[o] == keyy) return size[ch[o][0]]+1;
77     if (key[o] < keyy) return size[ch[o][0]]+cnt[o]+rank(ch[o][1], keyy);
78     return rank(ch[o][0], keyy);
79     }
80     int get_num(int o, int rk) {
81     if (size[ch[o][0]]+1 <= rk && rk <= size[ch[o][0]]+cnt[o]) return key[o];
82     if (rk <= size[ch[o][0]]) return get_num(ch[o][0], rk);
83     return get_num(ch[o][1], rk-size[ch[o][0]]-cnt[o]);
84     }
85     int get_pre(int o, int keyy, int ans) {
86     if (!o) return ans;
87     if (key[o] >= keyy) return get_pre(ch[o][0], keyy, ans);
88     ans = Max(ans, key[o]);
89     return get_pre(ch[o][1], keyy, ans);
90     }
91     int get_nex(int o, int keyy, int ans) {
92     if (!o) return ans;
93     if (key[o] <= keyy) return get_nex(ch[o][1], keyy, ans);
94     ans = Min(ans, key[o]);
95     return get_nex(ch[o][0], keyy, ans);
96     }
97 }T;
98 int n, opt, x;
99
100 void work() {
101     srand(time(0));
102     scanf("%d", &n);
103     while (n--) {
104     scanf("%d%d", &opt, &x);
105     if (opt == 1) T.insert(T.root, x);
106     else if (opt == 2) T.delet(T.root, x);
107     else if (opt == 3) printf("%d\n", T.rank(T.root, x));
108     else if (opt == 4) printf("%d\n", T.get_num(T.root, x));
109     else if (opt == 5) printf("%d\n", T.get_pre(T.root, x, -INF));
110     else printf("%d\n", T.get_nex(T.root, x, INF));
111     }
112 }
113 int main() {
114     work();
115     return 0;
116 }
Treap

### 4 fhq_Treap

  1 //It is made by Awson on 2017.12.15
2 #include <map>
3 #include <set>
4 #include <cmath>
5 #include <ctime>
6 #include <queue>
7 #include <stack>
8 #include <cstdio>
9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #define LL long long
16 #define Max(a, b) ((a) > (b) ? (a) : (b))
17 #define Min(a, b) ((a) < (b) ? (a) : (b))
18 using namespace std;
19 const int N = 100000;
20 const int INF = ~0u>>1;
21
22 struct fhq_Treap {
23     int ch[N+5][2], lev[N+5], size[N+5], key[N+5], tot, root;
24     queue<int>mem;
25     int newnode(int keyy) {
26     int o;
27     if (!mem.empty()) o = mem.front(), mem.pop();
28     else o = ++tot;
29     ch[o][0] = ch[o][1] = 0;
30     size[o] = 1;
31     key[o] = keyy, lev[o] = rand();
32     return o;
33     }
34     void pushup(int o) {
35     size[o] = size[ch[o][0]]+size[ch[o][1]]+1;
36     }
37     void split(int o, int keyy, int &x, int &y) {
38     if (!o) x = y = 0;
39     else {
40         if (key[o] <= keyy) x = o, split(ch[o][1], keyy, ch[o][1], y);
41         else y = o, split(ch[o][0], keyy, x, ch[o][0]);
42         pushup(o);
43     }
44     }
45     int merge(int x, int y) {
46     if (!x || !y) return x+y;
47     if (lev[x] < lev[y]) {
48         ch[x][1] = merge(ch[x][1], y);
49         pushup(x); return x;
50     }else {
51         ch[y][0] = merge(x, ch[y][0]);
52         pushup(y); return y;
53     }
54     }
55     void insert(int keyy) {
56     int r1, r2; split(root, keyy, r1, r2);
57     root = merge(merge(r1, newnode(keyy)), r2);
58     }
59     void delet(int keyy) {
60     int r1, r2, r3; split(root, keyy-1, r1, r2);
61     split(r2, keyy, r2, r3);
62     mem.push(r2);
63     r2 = merge(ch[r2][0], ch[r2][1]);
64     root = merge(merge(r1, r2), r3);
65     }
66     int rank(int keyy) {
67     int r1, r2; split(root, keyy-1, r1, r2);
68     int ans = size[r1]+1;
69     root = merge(r1, r2);
70     return ans;
71     }
72     int get_num(int o, int rk) {
73     if (size[ch[o][0]]+1 == rk) return key[o];
74     if (size[ch[o][0]] >= rk) return get_num(ch[o][0], rk);
75     return get_num(ch[o][1], rk-1-size[ch[o][0]]);
76     }
77     int get_pre(int keyy) {
78     int r1, r2; split(root, keyy-1, r1, r2);
79     int o = r1;
80     while (ch[o][1]) o = ch[o][1];
81     int ans = key[o];
82     root = merge(r1, r2);
83     return ans;
84     }
85     int get_nex(int keyy) {
86     int r1, r2; split(root, keyy, r1, r2);
87     int o = r2;
88     while (ch[o][0]) o = ch[o][0];
89     int ans = key[o];
90     root = merge(r1, r2);
91     return ans;
92     }
93 }T;
94 int n, opt, x;
95
96 void work() {
97     srand(time(0));
98     scanf("%d", &n);
99     while (n--) {
100     scanf("%d%d", &opt, &x);
101     if (opt == 1) T.insert(x);
102     else if (opt == 2) T.delet(x);
103     else if (opt == 3) printf("%d\n", T.rank(x));
104     else if (opt == 4) printf("%d\n", T.get_num(T.root, x));
105     else if (opt == 5) printf("%d\n", T.get_pre(x));
106     else printf("%d\n", T.get_nex(x));
107     }
108 }
109 int main() {
110     work();
111     return 0;
112 }
fhq_Treap
posted @ 2017-12-16 14:01  NaVi_Awson  阅读(277)  评论(0编辑  收藏  举报