最近“hiho一下”出了平衡树专题,这周的Splay一直出现RE,应该删除操作指针没处理好,还没找出原因。

  不过其他操作运行正常,尝试用它写了一道之前用set做的平衡树的题http://codeforces.com/problemset/problem/675/D,运行效果居然还挺好的,时间快了大概10%,内存少了大概30%。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <string>
  4 #include <cstdlib>
  5 #include <cctype>
  6 #include <cmath>
  7 #include <algorithm>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <stack>
 12 #include <queue>
 13 #include <assert.h>
 14 #define FREAD(fn) freopen((fn), "r", stdin)
 15 #define RINT(vn) scanf("%d", &(vn))
 16 #define PINT(vb) printf("%d", vb)
 17 #define RSTR(vn) scanf("%s", (vn))
 18 #define PSTR(vn) printf("%s", (vn))
 19 #define CLEAR(A, X) memset(A, X, sizeof(A))
 20 #define REP(N) for(i=0; i<(N); i++)
 21 #define REPE(N) for(i=1; i<=(N); i++)
 22 #define pb(X) push_back(X)
 23 #define pn() printf("\n")
 24 using namespace std;
 25 const int MAX_N = 100005;
 26 const int MAX_K = 0x7fffffff;
 27 const int MIN_K = 0;
 28 
 29 int a[MAX_N];
 30 int n;
 31 int i;
 32 map<int, bool> left, right;//iostream里有和left, right冲突的命名!
 33 
 34 struct Node
 35 {
 36     int k;
 37     Node *l, *r, *p;
 38     Node():k(-1), l(NULL), r(NULL), p(NULL){}
 39     Node(int kk, Node* pp):k(kk), l(NULL), r(NULL), p(pp){}
 40     ~Node(){
 41         l = r = p = NULL;
 42     }
 43 };
 44 
 45 struct Splay
 46 {
 47     Node* root;
 48     Node* _hot;
 49     Splay():root(NULL), _hot(NULL){}
 50     Splay(int k):root(new Node(k, NULL)), _hot(root){}
 51 
 52     void release(Node* cur){//释放子树cur的空间
 53         if(cur == NULL) return ;//空树
 54         release(cur->l);
 55         cur->l = NULL;
 56         release(cur->r);
 57         cur->r = NULL; //不用加吧,cur马上就销毁了啊
 58         //printf("deleted %d\n", cur->k);
 59 
 60         delete cur;
 61         return ;
 62     }
 63     ~Splay(){
 64         release(root);
 65         root = NULL;
 66     }
 67     void zig(Node* cur){
 68         if(cur == NULL) return ;
 69         Node* v = cur->l;
 70         if(v == NULL) return ;
 71         Node* g = cur->p;
 72 
 73         v->p = g;
 74         if(g != NULL)
 75             //祖先g与v连接
 76             (cur == g->l) ? g->l = v : g->r = v;
 77         
 78         //v与cur孩子过继
 79         cur->l = v->r;
 80         if(cur->l != NULL) cur->l->p = cur;
 81 
 82         //v与cur角色转换
 83         cur->p = v;
 84         v->r = cur;
 85         if(cur == root) root = v;
 86         //printf("%d zigged\n", cur->k);
 87     }
 88     void zag(Node* cur){
 89         if(cur == NULL) return ;
 90         Node* v = cur->r;
 91         if(v == NULL) return ;
 92         Node* g = cur->p;
 93         //printf("g=%d cur=%d v=%d\n", g->k, cur->k, v->k);
 94         
 95         v->p = g;
 96         if(g != NULL)
 97             (cur == g->l) ? g->l = v : g->r = v;
 98 
 99         cur->r = v->l;
100         if(cur->r != NULL) cur->r->p = cur;
101 
102         cur->p = v;
103         v->l = cur;
104         if(cur == root) root = v;
105         //printf("%d zagged\n", cur->k);
106     }
107     void splay(Node* x, Node* f){// make x become f's child
108         if(x == NULL) return ;
109         while(x->p != f){//逐步双层伸展
110             Node* p = x->p;
111             if(p == NULL) return ;
112             if(p->p == f)
113                 (x == p->l) ? zig(p) : zag(p);
114             else{
115                 Node* g = p->p;
116                 if(g == NULL) return ;
117                 if(g->l == p){
118                     if(p->l == x){
119                         zig(g); zig(p);
120                     }else{
121                         zag(p); zig(g);
122                     }
123                 }else{
124                     if(p->l == x){
125                         zig(p); zag(g);
126                     }else{
127                         zag(g); zag(p);
128                     }
129                 }
130             }    
131         }
132     }
133     Node* search(Node* cur, int k){//在cur子树中查找关键码k
134         if(cur == NULL) return _hot;//查找失败还伸展吗?暂不伸展,待决定插入后再将新插入的节点伸展
135         if(cur->k == k){//查找成功
136             //printf("has %d\n", cur->k);
137             splay(cur, NULL);//将目标节点伸展至根
138             return cur;
139         }
140         _hot = cur;//需要深入子树查找
141         return (k < cur->k) ? search(cur->l, k) : search(cur->r, k);
142     }
143     Node* insert(Node* cur, int k){//将关键码k插入cur子树
144         if(cur == NULL){//找到目标插入位置
145             cur = new Node(k, _hot);
146             //printf("%d %d\n", _hot->k, k);
147             (k < _hot->k) ? _hot->l=cur : _hot->r=cur;
148             _hot = cur;
149             //printf("create %d\n", cur->k);
150             splay(cur, NULL);//将目标节点伸展至树根
151             return cur;
152         }
153         assert(cur);
154         _hot = cur;//进入子树
155         //printf("enter %d\n", cur->k);
156         return (k < cur->k) ? insert(cur->l, k) : insert(cur->r, k);//assert:关键码互异
157     }
158     Node* prev(int k){//寻找关键码k的中序前驱
159         splay(search(root, k), NULL);//将k伸展至树根
160         Node* cur = root->l;//根节点的左子树
161         //assert(cur);
162         if(!cur) return NULL;
163         while(cur->r != NULL) cur = cur->r;//前驱必然为左子树的最右节点
164         return cur;
165     }
166     Node* succ(int k){//寻找关键码k的中序后继, assert:k一定存在
167         splay(search(root, k), NULL);
168         Node* cur = root->r;
169         //assert(cur);
170         if(!cur) return NULL;
171         while(cur->l != NULL) cur = cur->l;
172         return cur;
173     }
174     void deleteK(int k){//删除关键码k
175         Node* p = prev(k);
176         Node* s = succ(k);
177         splay(p, NULL);
178         splay(s, p);
179         Node* q = s->l;
180         s->l = NULL;//解除父子关系
181         release(q);//释放子树空间,这里只有一个节点k
182     }
183     void deleteInterval(int a, int b){//删除区间[a,b]内的关键码
184         Node* pa = search(root, a);//pa为最后一个被访问的节点,必不空
185         assert(pa);
186         if(pa->k != a) pa = insert(pa, a);//查找失败,插入
187         //printf("pa->k = a = %d\n", pa->k);
188 
189         Node* pb = search(root, b);
190         assert(pb);
191         //printf("pb->k = b = %d\n", pb->k);
192         if(pb->k != b) pb = insert(pb, b);
193         
194         Node* p = prev(a);
195         assert(p);
196         Node* s = succ(b);//assert: p, s not null
197         assert(s);
198         //printf("prev %d succ %d\n", p->k, s->k);
199         splay(p, NULL);
200         //printf("%d splayed\n", p->k);
201         splay(s, p);
202         //printf("%d splayed\n", s->k);
203         Node* q = s->l;
204         _hot = s;
205         release(q);//释放子树空间
206         s->l = NULL;
207     }
208 };
209 
210 int main()
211 {
212     FREAD("675d.txt");
213     RINT(n);
214     REP(n) RINT(a[i]);
215     Splay mySplay(a[0]);
216     for(i=1; i<n; i++){
217         // Node* p = mySplay.search(mySplay.root, a[i]);//必然失败
218         // if(p->k > a[i]) 
219         //     printf("%d\n", mySplay.prev(p->k));
220         // else printf("%d\n", p->k);
221         int ans = 0;
222         Node* q = mySplay.insert(mySplay.root, a[i]);
223         Node* p = mySplay.prev(a[i]);
224         if(p && right.count(p->k) == 0){
225             right[p->k] = 1;//前驱没有右孩子
226             ans = p->k;
227         }else{
228             Node* s = mySplay.succ(a[i]);
229             if(s && left.count(s->k) == 0){
230                 left[s->k] = 1;
231                 ans = s->k;
232             }
233         }
234         printf("%d\n", ans);
235     }
236     return 0;
237 }
CF 675D Splay

相关文章: