link
小 t 有乙個很大的書櫃。這個書櫃的構造有些獨特,即書櫃裡的書是從上至下堆放成一列。她用 \(1\) 到 \(n\) 的正整數給每本書都編了號。
小 t 在看書的時候,每次取出一本書,看完後放回書櫃然後再拿下一本。由於這些書太有吸引力了,所以她看完後常常會忘記原來是放在書櫃的什麼位置。不過小 t 的記憶力是非常好的,所以每次放書的時候至少能夠將那本書放在拿出來時的位置附近,比如說她拿的時候這本書上面有 \(x\) 本書,那麼放回去時這本書上面就只可能有 \(x−1\)、\(x\)或 \(x+1\) 本書。
當然也有特殊情況,比如在看書的時候突然**響了或者有朋友來訪。這時候粗心的小 t 會隨手把書放在書櫃裡所有書的最上面或者最下面,然後轉身離開。
久而久之,小 t 的書櫃裡的書的順序就會越來越亂,找到特定的編號的書就變得越來越困難。於是她想請你幫她編寫乙個圖書管理程式,處理她看書時的一些操作,以及回答她的兩個提問:
這道題的難點在於如何把編號和位置聯絡起來。支援乙個根據編號找位置的操作。
這裡令每本書的編號為權值,每本書的位置為排名
首先要把每個點權(\(x\))初始對應的編號(放在樹里的,就是\(tot\))記錄下來。
\(pos[x]=tot\)
並維護樹上結點的父親節點(馬上解釋為什麼)
每查詢乙個權值,就先把它的初始編號取出來,根據初始編號一直往上跳,
初始排名為自己的左子樹大小+1
兩種情況:
它是父親的右兒子:它的排名要加上它父親的左兒子的\(size\) ,然後往上跳
它是父親的左兒子:排名不變,往上跳
跳到根節點,返回排名(此權值的位置)
能夠由編號得到位置,問題也就解決了大半(≧▽≦)/啦啦啦
找到前驅/後繼交換位置時要精準。
以\(t==-1\)為例:
new1,new2表示合併順序
得到位置後記得減\(1\)
這裡直接給的位置,不用把\(pos[s]\)取出來了!!!
#include#define n (160010)
using namespace std;
struct xbkt[n];
int n,m,tot,rt,pos[n];
string opt;
inline int read()
while(ch>='0'&&ch<='9')
return f?-w:w;
}inline void update(int p)
inline int new(int val)
inline void split(int p,int k,int &a,int &b)
if(opt[0]=='b')
if(opt[0]=='i')
if(f==-1)
} if(opt[0]=='a')
if(opt[0]=='q')
} return 0;
}
ZJOI2006 書架 平衡樹
題目描述 小t有乙個很大的書櫃。這個書櫃的構造有些獨特,即書櫃裡的書是從上至下堆放成一列。她用1到n的正整數給每本書都編了號。小t在看書的時候,每次取出一本書,看完後放回書櫃然後再拿下一本。由於這些書太有吸引力了,所以她看完後常常會忘記原來是放在書櫃的什麼位置。不過小t的記憶力是非常好的,所以每次放...
ZJOI2006 書架(樹狀陣列水過)
這道題顯然平衡樹,splay,treap什麼的隨便切 然而我不想打,決定水過這道題 把空間開3倍,樹狀陣列維護它前面的樹的個數,開個id陣列記錄位置 找乙個數排名直接二分加求字首和,log 2的搞一搞 把乙個數放在頂 低 直接丟在當前頂 低的前後就可以了不然開3倍陣列幹嘛 c常數小堪比log的平衡樹...
P2596 ZJOI2006 書架 題解
最近學習了splay和非旋式treap,於是找到了這道題。維護乙個序列,支援移動元素,查詢元素在序列中的位置,查詢序列中某乙個位置的元素。無旋式treap可以維護一棵樹的中序遍歷結果,但是不支援通過編號來找節點。於是在無旋式treap的基礎上,維護每個節點的父親,這樣就可以求出元素在序列中的位置。對...