Splay总结及模板

https://blog.csdn.net/clove_unique/article/details/50630280

https://baijiahao.baidu.com/s?id=1613228134219334653&wfr=spider&for=pc

 

Tyvj 1728 普通平衡树

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

1.n的数据范围:n<=100000

2.每个数的数据范围:[-2e9,2e9]

#include<cstdio>
using namespace std;
const int N=100000+15;
int root,sz,ch[N][2],f[N],siz[N],cnt[N],val[N];

inline void clear(int x) {ch[x][0]=ch[x][1]=f[x]=siz[x]=cnt[x]=val[x]=0;}

inline int get(int x) {return ch[f[x]][1]==x;}

inline void pushup(int x) 
 {if(!x) return;
  siz[x]=cnt[x];
  if(ch[x][0]) siz[x]+=siz[ch[x][0]];
  if(ch[x][1]) siz[x]+=siz[ch[x][1]];
 }
inline void rotate(int x)
 {int fa=f[x],old=f[fa],wh=get(x);
 
  ch[fa][wh]=ch[x][wh^1]; f[ch[fa][wh]]=fa;
  
  ch[x][wh^1]=fa; f[fa]=x;
  
  f[x]=old;
  if(old) ch[old][ch[old][1]==fa]=x;
   
  pushup(fa); pushup(x); 
 }
 
inline void splay(int x)
 {while(f[x]!=0)
   {int y=f[x];int z=f[y];
        if(z!=0)
            (ch[z][1]==y)^(ch[y][1]==x)?rotate(x):rotate(y);
    rotate(x); 
   }	
 root=x; 
 } 
void insert(int x){
    int y=0,now=root;
    while(now&&val[now]!=x)y=now,now=ch[now][x>val[now]];
    if(now){cnt[now]++;pushup(now); }
    else {
        now=++sz; ch[sz][0]=ch[sz][1]=0; 
        cnt[now]=siz[now]=1;
        f[now]=y;val[now]=x;
        if(y)ch[y][x>val[y]]=now;
    }
    pushup(y);splay(now);
} 
inline int find(int x)
 {int re=0,now=root;
  while(1)
   {if(x<val[now]) now=ch[now][0];
    else {if(ch[now][0]) re+=siz[ch[now][0]];
          if(x==val[now]) {splay(now); return re+1;}
          
          re+=cnt[now];
          now=ch[now][1];
         }
   }
 } 
inline int getkth(int k)
 {int now=root;
  while(1)
   {if(ch[now][0] && k<=siz[ch[now][0]]) now=ch[now][0];
    else
      {int t=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now];
      
       if(k<=t) return val[now];
       k-=t; now=ch[now][1];
      }
   }
 } 
inline int pre()
 {int now=ch[root][0];
  while(ch[now][1]) now=ch[now][1];
  return now;
 } 
inline int nxt()
 {int now=ch[root][1];
  while(ch[now][0]) now=ch[now][0];
  return now;
 }  
inline void del(int x)
 { find(x);
  if(cnt[root]>1){cnt[root]--; pushup(root); return;}
  
  if(!ch[root][0]&&!ch[root][1]) {clear(root); root=0; return;}
  
  if(!ch[root][0])
   {int old=root; root=ch[root][1]; f[root]=0; clear(old); return;}
   
  if(!ch[root][1])
   {int old=root; root=ch[root][0]; f[root]=0; clear(old); return;} 
   
   int old=root; splay(pre());
   
   f[ch[old][1]]=root; ch[root][1]=ch[old][1];
   
   clear(old);
   pushup(root);
 }
int main()
{
 int n,opt,x; scanf("%d",&n);
 	
 while(n--)	
  {scanf("%d%d",&opt,&x);
  
	if(opt==1)      insert(x);
	else if(opt==2) del(x); 
	else if(opt==3) printf("%d\n",find(x));
	else if(opt==4) printf("%d\n",getkth(x));
	else if(opt==5) {insert(x); printf("%d\n",val[pre()]); del(x);
	                } 
	else if(opt==6) {insert(x); printf("%d\n",val[nxt()]); del(x);
	                } 
  }	
return 0;
}

 

【模板】文艺平衡树(Splay)

题目背景

这是一道经典的Splay模板题——文艺平衡树。

题目描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

输入输出格式

输入格式:

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2,⋯n−1,n)  m表示翻转操作次数

接下来m行每行两个数 [l,r]数据保证 1≤l≤r≤n

输出格式:

输出一行n个数字,表示原始序列经过m次变换后的结果

输入输出样例

输入样例#1: 

5 3

1 3

1 3

1 4

输出样例#1: 

4 3 2 1 5

说明

n,m≤100000 

 

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100000+15; const int inf=2147483640;
int n,root,sz,ch[N][2],siz[N],val[N],f[N],rev[N];

inline int get(int x) {return ch[f[x]][1]==x;}
inline void clear(int x){ch[x][0]=ch[x][1]=siz[x]=val[x]=f[x]=rev[x]=0;}
					      
inline void pushup(int x) {if(x)siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]]; }
inline void pass(int x) {rev[x]^=1;  swap(ch[x][0],ch[x][1]); }
inline void pushdown(int x) 
    {if(rev[x])
      {rev[x]=0; 
	   if(ch[x][0]) pass(ch[x][0]); 
	   if(ch[x][1]) pass(ch[x][1]);
      }     
    }
inline void rotate(int x)
 {int fa=f[x],old=f[fa],wh=get(x);
 
  ch[fa][wh]=ch[x][wh^1]; f[ch[fa][wh]]=fa;
  
  ch[x][wh^1]=fa; f[fa]=x;
  f[x]=old;
  if(old) ch[old][ch[old][1]==fa]=x;
  pushup(fa); pushup(x);
 }
inline void splay(int x,int aim)
 {
  while(f[x]!=aim)
   {int y=f[x],z=f[y];
        if(z!=aim)
            (ch[z][1]==y)^(ch[y][1]==x)?rotate(x):rotate(y);
    rotate(x); 
   }	
 	
  if(aim==0) root=x; 
 } 
 
void insert(int x){
    int y=0,now=root;
    while(now&&val[now]!=x)y=now,now=ch[now][x>val[now]];
    if(now){pushup(now); }
    else {
        now=++sz; ch[sz][0]=ch[sz][1]=0; 
        siz[now]=1;
        f[now]=y;val[now]=x;
        if(y)ch[y][x>val[y]]=now;
    }
    if(y) pushup(y);splay(now,0);
} 
inline int getkth(int k)
 {int now=root;
  while(1)
   {pushdown(now);
    if(k<=siz[ch[now][0]]) now=ch[now][0];
    else if(siz[ch[now][0]]+1==k) return now;
    else k=k-siz[ch[now][0]]-1,now=ch[now][1];
   }
  
 }
void print(int x)
 {pushdown(x);
  if(ch[x][0]) print(ch[x][0]);
  if(val[x]>1 && val[x]<n+2) printf("%d ",val[x]-1);
  if(ch[x][1]) print(ch[x][1]);
 }  
int main()
{
 int m,x,y; scanf("%d%d",&n,&m);	
  for(int i=1;i<=n+2;++i)insert(i);
 	
 while(m--)	
  {scanf("%d%d",&x,&y);
   x=getkth(x),y=getkth(y+2);
   splay(x,0); splay(y,x);
   pass(ch[ch[root][1]][0]);
  }		
	
 print(root);	
return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值