A Note on Non-Rotating Trep Learning

Keywords: Programming less PHP

Said ahead

After a long time in the pit, we can learn something when we meet some problems.
It's said that besides LCT, it's almost the same thing as splay to maintain the balance tree. It seems that LCT can also be implemented with treap.

Treap

As the name implies, Tree+Heap, or tree heap, has both the nature of binary search tree and heap. It usually uses the order of intermediate traversal and the height of heap as loglog log to solve many problems, which belongs to the category of balanced tree.
Essentially Cartesian tree, each point has two weights val, key val, key val, key, Val val val, that is to sort the weight, key key key is a random weight, used to maintain the nature of the heap, because the weight is random, the height of the small root heap built here is log log log, so all path operations and subtree operations on Treap are O (log) O (log).

Non spin Treap

Compared with the general rotating Treap, Treap is static, so it can support persistent operations and other Sao operations.
Non-rotating Treap has two core operations: split ting and merging.
split(x,k): Represents splitting x x x Treap into two Treaps that traverse the previous K and the remaining two Treaps in middle order, returning the roots of the two Treaps. It is a recursive operation that preserves the nature of Treap when splitting.

pr split(int x,int k){//sz is the size of subtree, pr is pair < int, int >
	if(!x) return pr(0,0);
	pr y;
	if(sz[tr[x].l]>=k){
		y=split(tr[x].l,k);
		tr[x].l=y.second,update(x);
		y.second=x;
	}
	else{
		y=split(tr[x].r,k-sz[tr[x].l]-1);
		tr[x].r=y.first,update(x);
		y.first=x;
	}
	return y;
}

merge(x,y): Based on the merging of random weights, the tree height of Treap after operation is still loglog. It is also a recursive process.

int merge(int x,int y){//tr[x].k is the random weight key.
	if(!x || !y) return x^y;
	if(tr[x].k<tr[y].k) return tr[x].r=merge(tr[x].r,y),update(x),x;
	else return tr[y].l=merge(x,tr[y].l),update(y),y;
}

With split and merge, we can implement many operations, such as insertion: finding the ranking k of the insertion point XXX on Treap, splitting Treap into the Treapx_xx of the previous k and the remaining Treapy_yy, merging Treapx_xx, xxx, Treapy_yy in turn. Deletion is similar, and sequence interval operations can be analogized.

The code is very short, and the constant is much less than the splay of spread complexity.
Examples (templates): BZOJ3224
A few more operations, pay attention to the ranking is to find the smallest.

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;++i)
#define fd(i,j,k) for(int i=j;i>=k;--i)
using namespace std;
const int N=1e5+10,inf=2147483647;
typedef pair<int,int> pr;
struct treap{
	int l,r,v,k;
}tr[N];
int rt;
int sz[N];
void update(int x){
	sz[x]=sz[tr[x].l]+sz[tr[x].r]+1;
}
int tot=0;
int merge(int x,int y){
	if(!x || !y) return x^y;
	if(tr[x].k<tr[y].k) return tr[x].r=merge(tr[x].r,y),update(x),x;
	else return tr[y].l=merge(x,tr[y].l),update(y),y;
}
pr split(int x,int k){
	if(!x) return pr(0,0);
	pr y;
	if(sz[tr[x].l]>=k){
		y=split(tr[x].l,k);
		tr[x].l=y.second,update(x);
		y.second=x;
	}
	else{
		y=split(tr[x].r,k-sz[tr[x].l]-1);
		tr[x].r=y.first,update(x);
		y.first=x;
	}
	return y;
}
int find(int k){
	pr x=split(rt,k-1),y=split(x.second,1);
	int t=y.first;
	rt=merge(merge(x.first,t),y.second);
	return tr[t].v;
}
int rank(int x,int v){
	int tmp=inf,t=0;
    while(x){
        if(v==tr[x].v) tmp=min(tmp,t+sz[tr[x].l]+1);
        if(v>tr[x].v) t+=sz[tr[x].l]+1,x=tr[x].r;
        else x=tr[x].l;
    }
    return tmp==inf?t:tmp;
}
void insert(int v){
	int k=rank(rt,v);
	pr x=split(rt,k);
	sz[++tot]=1,tr[tot].v=v,tr[tot].k=rand();
	rt=merge(merge(x.first,tot),x.second);
}
void del(int v){
	int k=rank(rt,v);
	pr x=split(rt,k-1),y=split(x.second,1);
	rt=merge(x.first,y.second);
}
int next(int v){
	int x=rt,tmp=inf;
	while(x) tr[x].v>v?(tmp=min(tmp,tr[x].v),x=tr[x].l):x=tr[x].r;
	return tmp;
}
int last(int v){
	int x=rt,tmp=-inf;
	while(x) tr[x].v<v?(tmp=max(tmp,tr[x].v),x=tr[x].r):x=tr[x].l;
	return tmp;
}
int main()
{
	int n;
	scanf("%d",&n);
	while(n--){
		int op,x;
		scanf("%d %d",&op,&x);
		if(op==1) insert(x);
		else if(op==2) del(x);
		else if(op==3) printf("%d\n",rank(rt,x));
		else if(op==4) printf("%d\n",find(x));
		else if(op==5) printf("%d\n",last(x));
		else printf("%d\n",next(x));
	}
}

Posted by ziltech on Fri, 25 Jan 2019 04:39:14 -0800