文藝平衡樹演算法

2021-10-19 11:39:46 字數 3702 閱讀 7130

您需要寫一種資料結構,來維護乙個有序序列。

其中需要提供以下操作:翻轉乙個區間,例如原有序列是5 4 3 2 1,翻轉區間是[2,4],結果為5 2 3 4 1

a[5]=那麼存入文藝平衡樹之後,再中序遍歷的結果應該還是:。即下標從小到大,而不是裡面的值從小到大!這是與普通平衡樹的最大的不同!文藝平衡樹經過rotate旋轉之後,它的中序遍歷是不變的(即,下標從小到大)。但是讓這顆樹的一部分區間倒置之後。這個中序遍歷下標就不是遞增的了。

1.建樹

就像給線段樹建樹一樣,但是在原陣列的基礎上加乙個-inf,+inf。(比如原序列是1,2,3,4。你建樹的時候要給-inf,1,2,3,4,+inf建樹)

至於為什麼這樣做,就是為了可以給區間[ 1,n ]倒置

主函式:

int

main()

write

(root)

;//system("pause");

return0;

}

這個沒有輸入對應的n個數,而是用1,2,……n來代表,你也可以輸入

struct splay_tree

tr[n]

;void

pushup

(int x)

//更新節點資訊

void

pushdown

(int x)

//相當於線段樹操作的懶惰標記

中序遍歷輸出

void

write

(int now)

綠色的線就是輸出的過程,綠色的數字就是輸出順序

那麼最重要的區間翻轉操作,改怎麼找到翻轉區間呢(畢竟只有先找到了才能打上標記呀)

那麼實際上我們可以發現,在反轉區間[l~r]的時候,我們可以考慮利用splay的性質,將l-1翻轉至根節點,再將r+1翻轉至根節點的右兒子,類似這樣:

//將區間[l,r]翻轉

那麼至於旋轉操作的話和普通平衡樹是一樣的,這裡就不過多贅述了,只是在旋轉過程中不要忘了pushdown哦。

void

rotate

(int x)

完整**:

#include

using

namespace std;

const

int n=

1e5+

10,inf=

1e9+10;

struct splay_tree

tr[n]

;int a[n]

;int root,tot;

void

pushup

(int x)

void

pushdown

(int x)

}int

build_tree

(int fx,

int l,

int r)

void

rotate

(int x)

void

splay

(int x,

int s)

if(s==

0) root=x;

}int

kth(

int x)

else u=y;}}

void

turn

(int l,

int r)

//將區間[l,r]翻轉

void

write

(int now)

intmain()

write

(root)

;//system("pause");

return0;

}

除了區間翻轉,還可以實現

1.區間加

2.區間刪除

3.在第x個數後插入乙個數p

4.刪去第x個數(其實就是變相的區間刪除)

5.查詢區間最小值

6.查詢區間和

#include

using

namespace std;

const

int n=

1e5+

10,inf=

1e9+10;

struct splay_tree

tr[n]

;int a[n]

;int root,tot;

void

pushup

(int x)

void

pushdown

(int x)

if(x&&tr[x]

.add)

//區間加標記

}int

build_tree

(int fx,

int l,

int r)

void

rotate

(int x)

void

splay

(int x,

int s)

if(s==

0) root=x;

}int

kth(

int x)

else u=y;}}

//下面為各種操作

void

turn

(int l,

int r)

//將區間[l,r]翻轉

void

delete

(int l,

int r)

//區間刪除

void

insert

(int x,

int y)

//在第x個數之後插入數p

void

add(

int l,

int r,

int x)

//區間加

void

write

(int now)

intmain()

else

if(op==2)

//區間刪除操作

else

if(op==3)

//在第x個數後插入數p

else

if(op==4)

//區間加

}write

(root)

;//system("pause");

return0;

}

有些我也沒在題目裡交過,如果有錯,望告知。

文藝平衡樹

和splay差不多,就是維護區間,把siz值為l 1 1與r 1 1的兩個節點,將乙個旋轉到根,另乙個旋轉到根的右兒子上,則要修改的區間就是根的右孩子的左子樹,直接打標記即可。推薦 遠航之曲dalao writer hsz wjmzbmr tourist hzwer include include ...

文藝平衡樹

前置知識 普通平衡樹。實際上,平衡樹能做到的操作不只有插入刪除,查排名查值,前驅後繼這些。如果我們把平衡樹移到區間上,我們甚至能夠支援比線段樹更強的操作 區間翻轉。這就是文藝平衡樹這道題了。首先我們來明確一下區間樹的概念。顧名思義,區間樹就是用來維護區間的。具體地,我們規定平衡樹的中序遍歷得到的數列...

模板 文藝平衡樹

由於中序遍歷不會因為旋轉改變,平衡樹可以作為區間樹使用。翻轉用打標記的方法,splay x,y 代表把x接到以y為根的子樹下面。include include using namespace std const int maxn 100005 int n,m int val maxn siz max...