FHQ Treap樹(無旋Treap樹)模板向

2021-09-29 07:52:03 字數 4328 閱讀 7876

這種樹是一種無需旋轉操作的treap樹,由fhq(範浩強)大佬發明,堪稱是神級的資料結構!他短小精悍,易於學習,而其思想之優雅令無數oier/acmer以及程式設計師們為之著迷!

在了解這個資料結構之前最好先了解一下treap樹以及笛卡爾樹,這兩種樹本身具有一定的相似性,而為fhq_treap提供了思想延申的起點。

fhq_treap代替旋轉操作的核心就是樹的分離(split)與合併(merge)兩種操作,使得我們可以將原樹按照值/位置(下標)分解為兩棵樹,以及將兩棵樹合併為一棵平衡的樹,而剩下的一切操作均基於這兩種操作!

按值的split:

void

split

(int x ,

int k,

int&l,

int&r)

//到空節點返回0

pushdown

(x);

if(val[x]

<=k)

//x分給左樹,接著分x的右兒子

else

//x分給右樹,接著分x的左兒子

}

按權值**應用於維護有序序列時(模擬於stl的set,或堆),可以查詢kth大等

按下標的split:

void

split

(int x,

int k,

int&l,

int&r)

pushdown

(x);

if(sz[ls[x]]+

1<=k)

//注意修改k

else

}

按下標**用於維護普通序列,可進行插入節點、區間和查詢、rmq、區間修改等

合併(merge):

int

merge

(int x,

int y)

// 合併

else

}

split與merge的pushup與pushdown按具體情況自行增刪修改即可。

鑑於本帖為模板向,不詳細解釋其背後原理(其實是自己不太會啦。。)

直接上題!!

#include

using

namespace std;

typedef

long

long ll;

typedef

unsigned

long

long usi;

const ll mod =

998244353

;const

int maxn =

1e5+7;

const

int inf =

0x3f3f3f3f

;const

double pi =

acos(-

1.0)

;const

double eps =

1e-12

;int ch[maxn][3

], val[maxn]

, pri[maxn]

, sz[maxn]

;class

fhq_treap

void

insert

(int a)

void

erase

(int a)

intnumrank

(int a)

intkth

(int k)

intpre

(int a)

intnext

(int a)

private

:int root =

0, x, y, z;

void

update

(int x)

intnewnode

(int v)

intmerge

(int x,

int y)

else

}void

split

(int now,

int k,

int&x,

int&y)

}int

myrank

(int now,

int a)}}

;fhq_treap mytree;

intmain()

return0;

}

本題使用了建笛卡爾樹的方法優化建樹到o(n)

#include

using

namespace std;

typedef

long

long ll;

const

int maxn =

2e5+5;

struct fhq_treap

node

(int ls,

int rs,

int rnd,

int siz, ll val, ll sum, ll lazy):ls

(ls),rs

(rs)

,rnd

(rnd)

,siz

(siz)

,val

(val)

,sum

(sum)

,lazy

(lazy)

}tree[maxn]

;inline

void

pushup

(int p)

inline

void

pushdown

(int p)

}void

split

(int p,

int rk,

int&x,

int&y)

pushdown

(p);

if(rk <= tree[tree[p]

.ls]

.siz)

else

}int

merge

(int x,

int y)

else

}int

newnode

(ll v)

void

insert

(ll val,

int p)

void

add(

int l,

int r, ll v)

void

query

(int l,

int r)

int st[maxn]

, top;

inline

void

build

(int n)

//用建笛卡爾樹的方法o(n)建樹,st為棧,返回新樹的根

if(top) tree[st[top]

].rs = tmp;

tree[tmp]

.ls = last;

st[++top]

= tmp;

}while

(top)

pushup

(st[top--])

; root = st[1]

;}} mytree;

intmain()

return0;

}

#include

#include

#include

#define n 100005

int root;

int lazy[n]

;int n,m,cnt;

int val[n]

,sze[n]

;int ch[n][2

],prio[n]

;void

pushup

(int o)

void

pushdown

(int o)

void

split

(int o,

int k,

int&x,

int&y)

}int

merge

(int x,

int y)

else

}int

newnode

(int v)

void

res(

int l,

int r)

void

dfs(

int now)

signed

main()

//printf("root=%d\n",root);

dfs(root)

;return0;

}

Fhq Treap無旋Treap練習

洛谷p3369 模板 普通平衡樹 split採用按權 author revolia submit includeusing namespace std typedef long long ll const int maxn 1e6 5 int l maxn r maxn val maxn size ...

fhq treap(無旋treap) 學習筆記

首先最好要會寫treap 也先了解一下笛卡爾樹是什麼。fhq treap和treap同樣有乙個隨機分配的rnd值,用於平衡,但fhq treap不需要旋轉操作來維持平衡,因為有兩個神奇的操作merge和split 在兩種操作之前,要明確的一點是fhq treap依靠rnd值來維護平衡,把每個點按照小...

演算法學習 FHQ Treap (無旋Treap)

fhq treap和普通的treap都是乙個二叉搜尋堆,其同時滿足二叉樹的性質 左子樹的權值小於等於當前節點權值,右子樹權值大於當前節點權值 和堆的性質 對於小根堆,當前節點的優先順序是堆中最小的 fhq treap與一般的treap的不同之處主要在於 不用旋轉,用split和merge來為維護堆的...