splay模板基本操作

Splay模板指针实现

splay中序遍历维护原序列下标的顺序,翻转后这个顺序会改变,但是splay中第x个数代表变换后序列中第x个数

这样就可以直接查找变换后的序列

重在代码

文艺平衡树

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
    node *ls,*rs,*fa;
    node(int x);
    void pushdown();
    void pushup();
    int rev,num,sz;
}*null=new node(0),*root=null;//空指针可以直接建出来,NULL容易出错
node::node(int x)
{
    ls=rs=fa=null;
    sz=rev=0;
    num=x;         
}
void node ::pushdown()
{
     if(rev)//rev翻转标记,表示子节点是否翻转
     {
          ls->rev^=1;
          rs->rev^=1;
          swap(ls->ls,ls->rs);
          swap(rs->ls,rs->rs);
          rev=0; 
     }
}
void node :: pushup()
{
     sz=ls->sz+rs->sz+1;
}
struct Splay
{
      void up(node *&y,node *&x)
      {
          if(y==y->fa->ls) y->fa->ls=x;
          else if(y==y->fa->rs) y->fa->rs=x;
          y->fa=x;
          y->pushup();
          if(y==root) root=x;
      }
      void zig(node *x)//右旋
      {
           node *y=x->fa;
           y->pushdown();x->pushdown();//下传标记,顺序不能变,先传父节点,再传儿子节点
           y->ls=x->rs;
           x->rs->fa=y;
           x->rs=y;
           x->fa=y->fa;
           up(y,x);
      }
      void zag(node *x)//左旋
      {
           node *y=x->fa;
           y->pushdown();x->pushdown();
           y->rs=x->ls;
           x->ls->fa=y;
           x->ls=y;
           x->fa=y->fa;
           up(y,x);
      }
      void splay(node *x,node *tar)//把x旋到tar的子节点
     {
          while(1){
             node *y=x->fa,*z=y->fa;
             if(y==tar) break;
             if(z==tar){
                if(x==y->ls) zig(x);
                else zag(x);
                break;
             }
             if(x==y->ls){
                 if(y==z->ls) zig(y);//一字型先旋y
                 zig(x);
             }
             else{
                 if(y==z->rs) zag(y);
                 zag(x); 
             }
          }
          x->pushup();
      }
      node* findx(node *x,int y)//查找第y个数,y不是权值,是序列中的顺序
      {
           while(1){
              x->pushdown();
              if(y<=x->ls->sz)  x=x->ls;
              else
              {
                  y-=x->ls->sz;
                  if(y==1) break;
                  y--;
                  x=x->rs;
              }
           }
           return x;
      }
      void find(int x,int y)//找到要操作的区间
      {
           node *t1=findx(root,x);
           node *t2=findx(root,y);
           splay(t1,null);
           splay(t2,root);
      }
      void insert(node *&x,int y,node *z)//插入一个权值为y的数
      {
           if(x==null){
              x=new node(y);
              x->fa=z;
              splay(x,null);
              return ;
           }
           x->pushdown();
           insert(x->rs,y,x);    
      }
}sp;
int n,m,x,y;
int main()
{
   freopen("sph.in","r",stdin);
   freopen("sph.out","w",stdout);
    scanf("%d%d",&n,&m);
    sp.insert(root,INF,null);//建立0和n+1节点,方便翻转
    for(int i=1;i<=n;i++)
      sp.insert(root,i,null);
    sp.insert(root,INF,null);
    for(int i=1;i<=m;i++){
       scanf("%d%d",&x,&y);
       sp.find(x,y+2);//有0节点,注意下区间,操作区间【x,y】,把x-1旋到根,y+1旋到x-1的右儿子
       node *tmp=root->rs->ls;
       tmp->rev^=1;
       swap(tmp->ls,tmp->rs);
    }
    for(int i=2;i<=n+1;i++)
      printf("%d ",sp.findx(root,i)->num);
  //  while(1);
    return 0;
}



posted @ 2017-08-04 06:05  HunterxHunterl  阅读(157)  评论(0编辑  收藏  举报