Hihocoder 1329(splay)

Posted rpSebastian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hihocoder 1329(splay)相关的知识,希望对你有一定的参考价值。

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 }
View Code

 

以上是关于Hihocoder 1329(splay)的主要内容,如果未能解决你的问题,请参考以下文章

HihoCoder1677 : 翻转字符串(Splay)(区间翻转)

hihocoder #1333 : 平衡树·Splay2

hihocoder第233周

Codeforces 1329 题解

●POJ 1329 Circle Through Three Points

1329:例8.2细胞