旋转Treap

Posted luckyblock

tags:

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

几乎可被完全替代,没有卵用的DS。

//Treap
/*
By:Luckyblock
*/
#include <cstdio> 
#include <algorithm>
#include <ctype.h>
#define ls (t[now].Son[0])
#define rs (t[now].Son[1])
#define min std::min
#define max std::max
#define ll long long
const int MARX = 1e6 + 10;
const int INF = 1e9 + 7; 
//=============================================================
struct TreapNode
{
	int Son[2];
	int Val, Rnd;
	int Size, Cnt;
} t[MARX];
int N, NodeNum, Root;
//=============================================================
inline int read()
{
    int s = 1, w = 0; char ch = getchar();
    for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) s = -1;
    for(; isdigit(ch); ch = getchar()) w = (w << 1) + (w << 3) + (ch ^ ‘0‘);
    return s * w;
}
int NewNode(int Val)
{
	t[++ NodeNum].Val = Val, t[NodeNum].Rnd = rand();
	t[NodeNum].Size = t[NodeNum].Cnt = 1;
	return NodeNum;
}
void Pushup(int now) {t[now].Size = t[ls].Size + t[rs].Size + t[now].Cnt;}
void Build()
{
	Root = NewNode(- INF), t[Root].Son[1] = NewNode(INF);
	Pushup(Root);
}
void Rotate(int &now, int Dir) //0??1?? 
{
	int tmp = t[now].Son[Dir ^ 1];
	t[now].Son[Dir ^ 1] = t[tmp].Son[Dir];
	t[tmp].Son[Dir] = now;
	now = tmp;
	Pushup(t[now].Son[Dir]), Pushup(now);
}
void Insert(int &now, int Val) //
{
	if(! now) {now = NewNode(Val); return ;}
	if(Val == t[now].Val) t[now].Cnt ++;
	else 
	{
	  int Dir = (Val < t[now].Val ? 0 : 1);
	  Insert(t[now].Son[Dir], Val);
	  if(t[now].Rnd < t[t[now].Son[Dir]].Rnd) Rotate(now, Dir ^ 1);
	}
	Pushup(now);
}
void Delete(int &now, int Val) //
{
	if(! now) return ;
	if(Val == t[now].Val)
	{
	  if(t[now].Cnt > 1) {t[now].Cnt --, Pushup(now); return ;}
	  if(ls || rs)
	  {
	  	if(! rs || t[ls].Rnd > t[rs].Rnd) Rotate(now, 1), Delete(rs, Val);
	  	else Rotate(now, 0), Delete(ls, Val);
	  	Pushup(now);
	  }
	  else now = 0;
	  return ; 
	}
	Val < t[now].Val ? Delete(ls, Val) : Delete(rs, Val);
	Pushup(now);
}
int QueryRank(int now, int Val)
{
	if(! now) return 0;
	if(Val == t[now].Val) return t[ls].Size + 1;
	if(Val < t[now].Val) return QueryRank(ls, Val);
	return t[ls].Size + t[now].Cnt + QueryRank(rs, Val);
}
int Kth(int now, int Rank)
{
	if(! now) return INF;
	if(Rank <= t[ls].Size) return Kth(ls, Rank); //
	if(Rank <= t[ls].Size + t[now].Cnt) return t[now].Val;
	return Kth(rs, Rank - t[ls].Size - t[now].Cnt);
}
int QueryPrecursor(int Val)
{
	int now = Root, Pre;
	while(now)
	{
	  if(t[now].Val < Val) Pre = t[now].Val, now = rs;
	  else now = ls;
	}
	return Pre;
}
int QuerySuccessor(int Val)
{
	int now = Root, Next;
	while(now)
	{
	  if(t[now].Val > Val) Next = t[now].Val, now = ls;
	  else now = rs;
	}
	return Next;
}
//=============================================================
int main()
{
	srand(NULL);
	N = read(); Build();
	for(int i = 1; i <= N; i ++)
	{
	  int opt = read(),x = read();
	  if(opt == 1) Insert(Root, x);
	  if(opt == 2) Delete(Root, x);
	  if(opt == 3) printf("%d
", QueryRank(Root, x) - 1);
	  if(opt == 4) printf("%d
", Kth(Root, x + 1));
	  if(opt == 5) printf("%d
", QueryPrecursor(x));
	  if(opt == 6) printf("%d
", QuerySuccessor(x));
	}
	return 0;
}

以上是关于旋转Treap的主要内容,如果未能解决你的问题,请参考以下文章

可持久化Treap(fhq Treap,非旋转式Treap)学习(未完待续)

非旋转Treap详解

算法学习Fhq-Treap(无旋Treap)

旋转Treap

非旋Treap

模板非旋转Treap