P2596 ZJOI2006 書架 題解

2021-10-19 08:52:22 字數 1764 閱讀 4816

最近學習了splay和非旋式treap,於是找到了這道題。

維護乙個序列,支援移動元素,查詢元素在序列中的位置,查詢序列中某乙個位置的元素。

無旋式treap可以維護一棵樹的中序遍歷結果,但是不支援通過編號來找節點。於是在無旋式treap的基礎上,維護每個節點的父親,這樣就可以求出元素在序列中的位置。

對於乙個節點,每次將它向樹根跳如果它是父親的右兒子,那麼就將它父親的左子樹大小+1+1

+1計入結果

那麼如何計算父親呢?顯然,會改變父親的只有split和merge操作,那麼我只需要在這兩個函式中修改就可以了。在split的時候再傳兩個引數記錄父親,merge 的時候在修改兒子的同時將父親一起修改。

其他的都是無旋式treap的基本操作了。

#include

#define ll long long

#define inf 0x3f3f3f3f

#define pi 3.1415926535897932384626

using

namespace std;

inline

intread()

ch=getchar()

;}while

(isdigit

(ch)

)return w*s;

}const

int maxn=

8e4+10;

int n,m,id[maxn]

,a[maxn]

,root,r1,r2,r3,r4,cnt=0;

//id記錄某乙個書的編號對映到樹中的節點的編號

struct treapt[maxn]

;int

newnode

(int val)

voidup(

int x)

void

split

(int x,

int k,

int&a,

int&b,

int faa=0,

int fab=0)

if(k<=t[t[x]

.ch[0]

].size)

else

up(x);}

intmerge

(int x,

int y)

//直接在記錄兒子的時候同時修改父親

if(t[x]

.rd.rd)

else

}void

insert

(int pos,

int val)

bool

get(

int x)

intfind

(int cnt)

//cnt是節點編號

cnt=t[cnt]

.fa;

//因為若該節點時左兒子的話,向上走時中序遍歷在增大的

//如果是右兒子往上跳的話,父親的左子樹的所有節點的中序遍歷的結果都是小於我在查的節點,所以要計入答案

}return res;

}int

main()

char opt[

100]

;for

(int i=

1;i<=m;i++

)case

'b':

case

'i':

else

}break;}

case

'a':

case

'q':}}

return0;

}

題解 ZJOI2006 書架

link 小 t 有乙個很大的書櫃。這個書櫃的構造有些獨特,即書櫃裡的書是從上至下堆放成一列。她用 1 到 n 的正整數給每本書都編了號。小 t 在看書的時候,每次取出一本書,看完後放回書櫃然後再拿下一本。由於這些書太有吸引力了,所以她看完後常常會忘記原來是放在書櫃的什麼位置。不過小 t 的記憶力是...

ZJOI2006 書架 平衡樹

題目描述 小t有乙個很大的書櫃。這個書櫃的構造有些獨特,即書櫃裡的書是從上至下堆放成一列。她用1到n的正整數給每本書都編了號。小t在看書的時候,每次取出一本書,看完後放回書櫃然後再拿下一本。由於這些書太有吸引力了,所以她看完後常常會忘記原來是放在書櫃的什麼位置。不過小t的記憶力是非常好的,所以每次放...

洛谷P2596 書架 splay

給出 n 本書和 m 個操作,按照操作維護序列並輸出對應結果。建立書本編號對樹上節點的對映,對於 top 和 bottom 操作,先把其前驅旋到根,後繼旋到根的右兒子,目標節點就是根的右兒子的左兒子。記錄其節點編號,然後斷開,把節點加到樹的最前或者最後。對於 insert 操作,如果是 0 直接忽略...