ZJOI2006 書架 平衡樹

2021-08-30 06:44:27 字數 2881 閱讀 8308

題目描述

小t有乙個很大的書櫃。這個書櫃的構造有些獨特,即書櫃裡的書是從上至下堆放成一列。她用1到n的正整數給每本書都編了號。

小t在看書的時候,每次取出一本書,看完後放回書櫃然後再拿下一本。由於這些書太有吸引力了,所以她看完後常常會忘記原來是放在書櫃的什麼位置。不過小t的記憶力是非常好的,所以每次放書的時候至少能夠將那本書放在拿出來時的位置附近,比如說她拿的時候這本書上面有x本書,那麼放回去時這本書上面就只可能有x-1、x或x+1本書。

當然也有特殊情況,比如在看書的時候突然**響了或者有朋友來訪。這時候粗心的小t會隨手把書放在書櫃裡所有書的最上面或者最下面,然後轉身離開。

久而久之,小t的書櫃裡的書的順序就會越來越亂,找到特定的編號的書就變得越來越困難。於是她想請你幫她編寫乙個圖書管理程式,處理她看書時的一些操作,以及回答她的兩個提問:(1)編號為x的書在書櫃的什麼位置;(2)從上到下第i本書的編號是多少。

輸入輸出格式

輸入格式:

第一行有兩個數n,m,分別表示書的個數以及命令的條數;第二行為n個正整數:第i個數表示初始時從上至下第i個位置放置的書的編號;第三行到m+2行,每行一條命令。命令有5種形式:

1. top s——表示把編號為s的書放在最上面。

2. bottom s——表示把編號為s的書放在最下面。

3. insert s t——t∈,若編號為s的書上面有x本書,則這條命令表示把這本書放回去後它的上面有x+t本書;

4. ask s——詢問編號為s的書的上面目前有多少本書。

5. query s——詢問從上面數起的第s本書的編號。

輸出格式:

對於每一條ask或query語句你應該輸出一行,乙個數,代表詢問的答案。

輸入輸出樣例

輸入樣例#1: 複製

10 10

1 3 2 7 5 8 10 4 9 6

query 3

top 5

ask 6

bottom 3

ask 3

top 6

insert 4 -1

query 5

query 2

ask 2

輸出樣例#1: 複製29

9753

說明100%的資料,n,m <= 80000

首先要提的一點是這道題我用splay寫,當然也有大佬用fhq treap寫,但是我不會。

這道題以序列裡的位置作為splay的判斷值,而編號只是乙個附加值。

我們一一分析需要的操作:

1.top:找到編號為x的書的位置,將他splay到根,然後將它左兒子裡最小的點(也就是一直往左邊走的點)splay到son[root][0](根的左兒子),然後將root的右子樹合併到左子樹上(前提是保證平衡樹的性質),然後將root變為son[root][0]的左兒子,原來的son[root][0]變為新的root。

下面就是圖示:

2.bottom:這個操作類似於top,實際上打這個函式的時候就直接複製top,然後將函式裡的son[k][0]和son[k][1]掉換一下即可。

因為這兩個操作本質一樣,只不過bottom是將它旋到最後面的點。

給出bottom的**

void bottom(int x)

else

}

3.insert:這個操作其實就是交換兩個點的資訊(編號),所以直接將它們的資訊swap一下即可。

注意因為我們記錄了id陣列,id[x]表示編號為x的書在序列中的位置,而這個操作是要改變這個相對位置的,所以要將它們的id也swap一下。

void swaps(int x,int y)
4.ask:問多少本書在它上面,那麼我們只要把x旋轉splay到根,統計其左子樹的size即可(因為我們維護平衡樹的資訊就是其在序列中的位置,所以左子樹中的點在序列中的位置都小於它)

5.query:這個操作就很基礎了,是普通平衡樹的操作,查詢排名為k的數是哪個,這個操作可以去參考普通平衡樹(bzoj3224)的**。這裡就貼出**以便沒見過的同學理解(你們肯定會看得懂的)

當然這裡只返回了位置,所以最後輸出時要輸num[query(root,x)]

int query(int k,int x)
完整code:
#include#define maxn 80005

using namespace std;

int read()

void print(int x)

int n,m,root;

char c;

int fa[maxn],son[maxn][2],p[maxn],num[maxn],siz[maxn],id[maxn];

void up(int k)

int get(int k)

void build(int l,int r,int f)

void rotate(int x,int &k)

void splay(int x,int &k)

id[num[x]]=x;

}void top(int x)

else

}void bottom(int x)

else

}int ask(int x)

int query(int k,int x)

void swaps(int x,int y)

int main()

else if(c=='t')

else if(c=='b')

else if(c=='i')

else if(c=='a')

}return 0;

}

題解 ZJOI2006 書架

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

ZJOI2006 書架(樹狀陣列水過)

這道題顯然平衡樹,splay,treap什麼的隨便切 然而我不想打,決定水過這道題 把空間開3倍,樹狀陣列維護它前面的樹的個數,開個id陣列記錄位置 找乙個數排名直接二分加求字首和,log 2的搞一搞 把乙個數放在頂 低 直接丟在當前頂 低的前後就可以了不然開3倍陣列幹嘛 c常數小堪比log的平衡樹...

ZJOI2006 物流運輸

description 物流公司要把一批貨物從碼頭a運到碼頭b。由於貨物量比較大,需要n天才能運完。貨物運輸過程中一般要轉停好幾個碼頭。物流公司通常會設計一條固定的運輸路線,以便對整個運輸過程實施嚴格的管理和跟蹤。由於各種因素的存在,有的時候某個碼頭會無法裝卸貨物。這時候就必須修改運輸路線,讓貨物能...