• 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
  • 相关阅读:
    GIT笔记
    C++新式类型转换
    C++ 静态链表基本算法实现
    C++ 顺序栈基本算法实现
    C++ 链栈 基本算法实现
    C++ 循环队列基本算法实现
    C++ 链队列基本算法实现
    C++优先级队列表基本算法实现
    C++单链表基本算法实现
    C++ 循环链表基本算法
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/6771441.html
Copyright © 2020-2023  润新知