Problem 平衡树 Splay
题目大意
维护一个数列,支持三种操作。
操作1:添加一个数x。
操作2:询问不超过x的最大的数。
操作三:删除大小在区间【a,b】内的数。
解题分析
和上一题相比,多了一个删除的操作。
首先将a的前驱节点x旋转到根,然后将b的后驱节点y旋转到x的右孩子,这样所有大小在【a,b】内的数均位于y的左子树内,直接将其删掉就可以了。
为了防止找不到x和y,在初始化时向树中插入一个极大值和一个极小值。
参考程序
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct node{ 5 int val; 6 node *left,*right,*father; 7 node(int val_=0,node* father_=NULL,node* left_=NULL,node* right_=NULL) 8 { 9 val=val_; father=father_; left=left_; right=right_; 10 } 11 }*rt,*t1,*t2; 12 13 void search(node *now) 14 { 15 cout<<now<<" "<<now->val<<" "<<now->left<<" "<<now->right<<" "<<now->father<<endl; 16 if (now->left) search(now->left); 17 if (now->right) search(now->right); 18 } 19 20 void pushup(node *x) 21 { 22 } 23 24 void right(node* x,node* &rt) 25 { 26 node *y=x->father,*z=y->father; 27 if (y==rt) rt=x; 28 else if (z->left==y) z->left=x; else z->right=x; //需要判断是左右孩子 29 x->father=z; y->father=x; if (x->right) x->right->father=y; //防止对空指针进行操作 30 y->left=x->right; x->right=y; 31 pushup(y); pushup(x); 32 } 33 34 void left(node* x,node* &rt) 35 { 36 node *y=x->father,*z=y->father; 37 if (y==rt) rt=x; 38 else if (z->left==y) z->left=x; else z->right=x; 39 x->father=z; y->father=x; if (x->left) x->left->father=y; 40 y->right=x->left; x->left=y; 41 pushup(y); pushup(x); 42 } 43 44 void splay(node* x,node* &rt) 45 { 46 while (x!=rt) 47 { 48 node *y=x->father, *z=y->father; 49 if (y==rt) 50 { 51 if (x==y->left) right(x,rt); 52 else left(x,rt); 53 } 54 else 55 { 56 if (y==z->left) 57 if (x==y->left) { right(y,rt); right(x,rt); } 58 else { left(x,rt); right(x,rt); } 59 else 60 if (x==y->right) { left(y,rt); left(x,rt); } 61 else { right(x,rt); left(x,rt); } 62 } 63 } 64 } 65 66 void insert(int val,node* &now,node *last) 67 { 68 if (now==NULL) 69 { 70 now=new node(val,last); 71 splay(now,rt); 72 return; 73 } 74 if (val < now->val) insert(val,now->left,now); else //else还是要加的 返回的时候树的形态已经改变了 75 if (val > now->val) insert(val,now->right,now); 76 } 77 78 int get(int val,node *x) 79 { 80 int res=-1<<30; 81 while (x!=NULL) 82 { 83 if (x->val>val) x=x->left; 84 else 85 { 86 res=max(res,x->val); 87 x=x->right; 88 } 89 } 90 return res; 91 } 92 93 void find_1(int val,node *x) 94 { 95 if (x==NULL) return; 96 if (x->val>=val) find_1(val,x->left); 97 else {t1=x; find_1(val,x->right);} 98 } 99 100 101 void find_2(int val,node *x) 102 { 103 if (x==NULL) return; 104 if (x->val<=val) find_2(val,x->right); 105 else {t2=x; find_2(val,x->left);} 106 } 107 108 void work(int l,int r) 109 { 110 t1=t2=NULL; 111 find_1(l,rt); splay(t1,rt); 112 find_2(r,rt->right); splay(t2,rt->right); 113 rt->right->left=NULL; 114 } 115 116 int main() 117 { 118 int n; 119 rt=NULL; 120 scanf("%d",&n); 121 insert(1<<30,rt,NULL); insert(-1<<30,rt,NULL); 122 for (int i=1;i<=n;i++) 123 { 124 char s[3]; int x,y; 125 scanf("%s%d",s,&x); 126 if (s[0]=='I') insert(x,rt,NULL); 127 if (s[0]=='Q') cout<<get(x,rt)<<endl; 128 if (s[0]=='D') 129 { 130 scanf("%d",&y); 131 if (x>y) swap(x,y); 132 work(x,y); 133 } 134 } 135 }