旋转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的主要内容,如果未能解决你的问题,请参考以下文章